From 37c02ddee1add2bafdbe49ce12edb1adbe08e4f8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 14 Apr 2012 12:03:03 +0000 Subject: [PATCH 001/183] Camera tracking: revert changes made for texture buffer frame drawing. Will be applied as another cleaned-up patch. --- release/scripts/startup/bl_ui/space_clip.py | 2 - source/blender/blenloader/intern/readfile.c | 1 - source/blender/editors/include/ED_clip.h | 4 - .../blender/editors/space_clip/CMakeLists.txt | 1 - source/blender/editors/space_clip/SConscript | 2 +- source/blender/editors/space_clip/clip_draw.c | 42 ++--- .../blender/editors/space_clip/clip_editor.c | 150 ------------------ .../blender/editors/space_clip/space_clip.c | 3 - source/blender/makesdna/DNA_space_types.h | 3 - source/blender/makesrna/intern/rna_space.c | 5 - 10 files changed, 12 insertions(+), 201 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 51a1751bb00..f83c66dc991 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -606,8 +606,6 @@ class CLIP_PT_display(Panel): elif sc.mode == 'RECONSTRUCTION': col.prop(sc, "show_stable", text="Stable") - col.prop(sc, "use_texture_buffer") - clip = sc.clip if clip: col.label(text="Display Aspect Ratio:") diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f82f10e83f5..e9a5dada044 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5385,7 +5385,6 @@ static void lib_link_screen(FileData *fd, Main *main) sclip->clip= newlibadr_us(fd, sc->id.lib, sclip->clip); sclip->scopes.track_preview = NULL; - sclip->draw_context = NULL; sclip->scopes.ok = 0; } } diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 8e3488203a2..5e8ef618a42 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -58,10 +58,6 @@ void ED_clip_point_undistorted_pos(SpaceClip *sc, float co[2], float nco[2]); void ED_clip_point_stable_pos(struct bContext *C, float x, float y, float *xr, float *yr); void ED_clip_mouse_pos(struct bContext *C, struct wmEvent *event, float co[2]); -void ED_space_clip_load_movieclip_buffer(struct SpaceClip *sc, struct ImBuf *ibuf); -void ED_space_clip_unload_movieclip_buffer(struct SpaceClip *sc); -void ED_space_clip_free_texture_buffer(struct SpaceClip *sc); - /* clip_ops.c */ void ED_operatormacros_clip(void); diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt index 30d2fe57c10..4f9819e8e77 100644 --- a/source/blender/editors/space_clip/CMakeLists.txt +++ b/source/blender/editors/space_clip/CMakeLists.txt @@ -31,7 +31,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../gpu ../../../../intern/guardedalloc ${GLEW_INCLUDE_PATH} ) diff --git a/source/blender/editors/space_clip/SConscript b/source/blender/editors/space_clip/SConscript index c9c82aea68e..70331b0ec4a 100644 --- a/source/blender/editors/space_clip/SConscript +++ b/source/blender/editors/space_clip/SConscript @@ -4,6 +4,6 @@ Import ('env') sources = env.Glob('*.c') defs = [] incs = '../include ../../blenkernel ../../blenloader ../../blenfont ../../blenlib ../../imbuf ../../makesdna' -incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../gpu' +incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #/extern/glew/include' env.BlenderLib ( 'bf_editors_space_clip', sources, Split(incs), defs, libtype=['core'], priority=[95] ) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 418b72dc944..2f9956fc143 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -229,6 +229,9 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, int x, y; MovieClip *clip = ED_space_clip(sc); + /* set zoom */ + glPixelZoom(zoomx*width/ibuf->x, zoomy*height/ibuf->y); + /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); @@ -239,35 +242,8 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, else { verify_buffer_float(ibuf); - if(ibuf->rect) { - if(sc->flag & SC_TEXTURE_BUFFER) { - ED_space_clip_load_movieclip_buffer(sc, ibuf); - - glPushMatrix(); - glTranslatef(x, y, 0.0f); - glScalef(zoomx, zoomy, 1.0f); - - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); - glTexCoord2f(1.0f, 0.0f); glVertex2f(width, 0.0f); - glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height); - glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, height); - glEnd(); - - glPopMatrix(); - - ED_space_clip_unload_movieclip_buffer(sc); - } - else { - /* set zoom */ - glPixelZoom(zoomx*width/ibuf->x, zoomy*height/ibuf->y); - - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - - /* reset zoom */ - glPixelZoom(1.0f, 1.0f); - } - } + if (ibuf->rect) + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); } /* draw boundary border for frame if stabilization is enabled */ @@ -279,9 +255,9 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, glLogicOp(GL_NOR); glPushMatrix(); - glTranslatef(x, y, 0.0f); + glTranslatef(x, y, 0); - glScalef(zoomx, zoomy, 1.0f); + glScalef(zoomx, zoomy, 0); glMultMatrixf(sc->stabmat); glBegin(GL_LINE_LOOP); @@ -296,6 +272,10 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_LINE_STIPPLE); } + + + /* reset zoom */ + glPixelZoom(1.0f, 1.0f); } static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackingTrack *track) diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index dcc4f66490a..3946d4cc36d 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -31,8 +31,6 @@ #include -#include "MEM_guardedalloc.h" - #include "BKE_main.h" #include "BKE_movieclip.h" #include "BKE_context.h" @@ -42,8 +40,6 @@ #include "BLI_utildefines.h" #include "BLI_math.h" -#include "GPU_extensions.h" - #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -51,7 +47,6 @@ #include "ED_clip.h" #include "BIF_gl.h" -#include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" @@ -319,148 +314,3 @@ void ED_clip_mouse_pos(bContext *C, wmEvent *event, float co[2]) { ED_clip_point_stable_pos(C, event->mval[0], event->mval[1], &co[0], &co[1]); } - -/* OpenGL draw context */ - -typedef struct SpaceClipDrawContext { - GLuint texture; /* OGL texture ID */ - short texture_allocated; /* flag if texture was allocated by glGenTextures */ - struct ImBuf *texture_ibuf; /* image buffer for which texture was created */ - int image_width, image_height; /* image width and height for which texture was created */ - unsigned last_texture; /* ID of previously used texture, so it'll be restored after clip drawing */ - int framenr; -} SpaceClipDrawContext; - -void ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) -{ - SpaceClipDrawContext *context = sc->draw_context; - MovieClip *clip = ED_space_clip(sc); - int need_rebind = 0; - - if (!context) { - context = MEM_callocN(sizeof(SpaceClipDrawContext), "SpaceClipDrawContext"); - sc->draw_context = context; - } - - context->last_texture = glaGetOneInteger(GL_TEXTURE_2D); - - /* image texture need to be rebinded if displaying another image buffer - * assuming displaying happens of footage frames only on which painting doesn't heppen. - * so not changed image buffer pointer means unchanged image content */ - need_rebind |= context->texture_ibuf != ibuf; - need_rebind |= context->framenr != sc->user.framenr; - - if (need_rebind) { - int width = ibuf->x, height = ibuf->y; - float *frect = NULL, *fscalerect = NULL; - unsigned int *rect = NULL, *scalerect = NULL; - int need_recreate = 0; - - rect = ibuf->rect; - frect = ibuf->rect_float; - - /* if image resolution changed (e.g. switched to proxy display) texture need to be recreated */ - need_recreate = context->image_width != ibuf->x || context->image_height != ibuf->y; - - if (context->texture_ibuf && need_recreate) { - glDeleteTextures(1, &context->texture); - context->texture_allocated = 0; - } - -#if 0 - /* disabled for now because current tracking users have got NPOT textures - * working smoothly on their computers and forcing re-scaling during playback - * slows down playback a lot */ - - /* if videocard doesn't support NPOT textures, need to do rescaling */ - if (!GPU_non_power_of_two_support()) { - if (!is_power_of_2_i(width) || !is_power_of_2_i(height)) { - width = power_of_2_max_i(width); - height = power_of_2_max_i(height); - - if (ibuf->x != width || ibuf->y != height) { - if (frect) { - fscalerect= MEM_mallocN(width*width*sizeof(*fscalerect)*4, "fscalerect"); - gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float, width, height, GL_FLOAT, fscalerect); - - frect = fscalerect; - } - else { - scalerect= MEM_mallocN(width*height*sizeof(*scalerect), "scalerect"); - gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect, width, height, GL_UNSIGNED_BYTE, scalerect); - - rect = scalerect; - } - } - } - } -#endif - - if (need_recreate || !context->texture_allocated) { - /* texture doesn't exist yet or need to be re-allocated because of changed dimensions */ - int filter = GL_LINEAR; - - /* non-scaled proxy shouldn;t use diltering */ - if ((clip->flag & MCLIP_USE_PROXY) == 0 || - ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100)) - { - filter = GL_NEAREST; - } - - glGenTextures(1, &context->texture); - glBindTexture(GL_TEXTURE_2D, context->texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - } - else { - /* if texture doesn't need to be reallocated itself, just bind it so - * loading of image will happen to a proper texture */ - glBindTexture(GL_TEXTURE_2D, context->texture); - } - - if (frect) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, width, height, 0, GL_RGBA, GL_FLOAT, frect); - else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); - - /* store settings */ - context->texture_allocated = 1; - context->texture_ibuf = ibuf; - context->image_width = ibuf->x; - context->image_height = ibuf->y; - context->framenr = sc->user.framenr; - - if (fscalerect) - MEM_freeN(fscalerect); - if (scalerect) - MEM_freeN(scalerect); - } - else { - /* displaying exactly the same image which was loaded t oa texture, - * just bint texture in this case */ - glBindTexture(GL_TEXTURE_2D, context->texture); - } - - glEnable(GL_TEXTURE_2D); -} - -void ED_space_clip_unload_movieclip_buffer(SpaceClip *sc) -{ - SpaceClipDrawContext *context = sc->draw_context; - - glBindTexture(GL_TEXTURE_2D, context->last_texture); - glDisable(GL_TEXTURE_2D); -} - -void ED_space_clip_free_texture_buffer(SpaceClip *sc) -{ - SpaceClipDrawContext *context = sc->draw_context; - - if (context) { - glDeleteTextures(1, &context->texture); - - MEM_freeN(context); - } -} diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index ddd8c1b6947..228c716e3b6 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -214,8 +214,6 @@ static void clip_free(SpaceLink *sl) if (sc->scopes.track_preview) IMB_freeImBuf(sc->scopes.track_preview); - - ED_space_clip_free_texture_buffer(sc); } /* spacetype; init callback */ @@ -231,7 +229,6 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) /* clear or remove stuff from old */ scn->scopes.track_preview = NULL; scn->scopes.ok = FALSE; - scn->draw_context= NULL; return (SpaceLink *)scn; } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index a05dd491b69..1938c63d474 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -523,8 +523,6 @@ typedef struct SpaceClip { int postproc_flag; int runtime_flag; /* different runtime flags */ - - void *draw_context; } SpaceClip; /* view3d Now in DNA_view3d_types.h */ @@ -906,7 +904,6 @@ enum { #define SC_SHOW_GRAPH_TRACKS (1<<15) /*#define SC_SHOW_PYRAMID_LEVELS (1<<16) */ /* UNUSED */ #define SC_LOCK_TIMECURSOR (1<<17) -#define SC_TEXTURE_BUFFER (1<<18) /* SpaceClip->mode */ #define SC_MODE_TRACKING 0 diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 7289a693820..5e0a20c51ad 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -3079,11 +3079,6 @@ static void rna_def_space_clip(BlenderRNA *brna) "for the selected tracks"); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); - prop= RNA_def_property(srna, "use_texture_buffer", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_ui_text(prop, "Use Texture Buffer", "Use texture buffer to display o,age frames frame on screen"); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_TEXTURE_BUFFER); - RNA_def_property_update(prop, NC_WINDOW, NULL); - /* ** channels ** */ /* show_red_channel */ From c3218ebdff43ad60d9e01b5fa13768e8416d7bd7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 14 Apr 2012 12:03:09 +0000 Subject: [PATCH 002/183] Camera tracking: use texture buffers (if supported) to display clip editor frames Initial idea was to perform bilinear filtering for displaying proxied frame to make it looking a bit smoother. It was done but it was also discovered that using such kind of texture buffers helps on some crappy videocards when playing $k footage. --- source/blender/blenloader/intern/readfile.c | 1 + source/blender/editors/include/ED_clip.h | 5 + .../blender/editors/space_clip/CMakeLists.txt | 1 + source/blender/editors/space_clip/SConscript | 2 +- source/blender/editors/space_clip/clip_draw.c | 49 +++-- .../blender/editors/space_clip/clip_editor.c | 169 ++++++++++++++++++ .../blender/editors/space_clip/space_clip.c | 5 +- source/blender/makesdna/DNA_space_types.h | 1 + 8 files changed, 220 insertions(+), 13 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e9a5dada044..f82f10e83f5 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5385,6 +5385,7 @@ static void lib_link_screen(FileData *fd, Main *main) sclip->clip= newlibadr_us(fd, sc->id.lib, sclip->clip); sclip->scopes.track_preview = NULL; + sclip->draw_context = NULL; sclip->scopes.ok = 0; } } diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 5e8ef618a42..4474ea7f281 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -58,6 +58,11 @@ void ED_clip_point_undistorted_pos(SpaceClip *sc, float co[2], float nco[2]); void ED_clip_point_stable_pos(struct bContext *C, float x, float y, float *xr, float *yr); void ED_clip_mouse_pos(struct bContext *C, struct wmEvent *event, float co[2]); +int ED_space_clip_texture_buffer_supported(struct SpaceClip *sc); +int ED_space_clip_load_movieclip_buffer(struct SpaceClip *sc, struct ImBuf *ibuf); +void ED_space_clip_unload_movieclip_buffer(struct SpaceClip *sc); +void ED_space_clip_free_texture_buffer(struct SpaceClip *sc); + /* clip_ops.c */ void ED_operatormacros_clip(void); diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt index 4f9819e8e77..30d2fe57c10 100644 --- a/source/blender/editors/space_clip/CMakeLists.txt +++ b/source/blender/editors/space_clip/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager + ../../gpu ../../../../intern/guardedalloc ${GLEW_INCLUDE_PATH} ) diff --git a/source/blender/editors/space_clip/SConscript b/source/blender/editors/space_clip/SConscript index 70331b0ec4a..c9c82aea68e 100644 --- a/source/blender/editors/space_clip/SConscript +++ b/source/blender/editors/space_clip/SConscript @@ -4,6 +4,6 @@ Import ('env') sources = env.Glob('*.c') defs = [] incs = '../include ../../blenkernel ../../blenloader ../../blenfont ../../blenlib ../../imbuf ../../makesdna' -incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #/extern/glew/include' +incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../gpu' env.BlenderLib ( 'bf_editors_space_clip', sources, Split(incs), defs, libtype=['core'], priority=[95] ) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 2f9956fc143..0d519f36ba3 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -229,9 +229,6 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, int x, y; MovieClip *clip = ED_space_clip(sc); - /* set zoom */ - glPixelZoom(zoomx*width/ibuf->x, zoomy*height/ibuf->y); - /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); @@ -242,8 +239,42 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, else { verify_buffer_float(ibuf); - if (ibuf->rect) - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + if (ibuf->rect) { + int need_fallback = 1; + + if (ED_space_clip_texture_buffer_supported(sc)) { + if (ED_space_clip_load_movieclip_buffer(sc, ibuf)) { + glPushMatrix(); + glTranslatef(x, y, 0.0f); + glScalef(zoomx, zoomy, 1.0f); + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); + glTexCoord2f(1.0f, 0.0f); glVertex2f(width, 0.0f); + glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height); + glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, height); + glEnd(); + + glPopMatrix(); + + ED_space_clip_unload_movieclip_buffer(sc); + + need_fallback = 0; + } + } + + /* if texture buffers aren't efifciently supported or texture is too large to + * be binder fallback to simple draw pixels solution */ + if (need_fallback) { + /* set zoom */ + glPixelZoom(zoomx*width/ibuf->x, zoomy*height/ibuf->y); + + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + + /* reset zoom */ + glPixelZoom(1.0f, 1.0f); + } + } } /* draw boundary border for frame if stabilization is enabled */ @@ -255,9 +286,9 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, glLogicOp(GL_NOR); glPushMatrix(); - glTranslatef(x, y, 0); + glTranslatef(x, y, 0.0f); - glScalef(zoomx, zoomy, 0); + glScalef(zoomx, zoomy, 1.0f); glMultMatrixf(sc->stabmat); glBegin(GL_LINE_LOOP); @@ -272,10 +303,6 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_LINE_STIPPLE); } - - - /* reset zoom */ - glPixelZoom(1.0f, 1.0f); } static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackingTrack *track) diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 3946d4cc36d..40be2622f95 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -31,6 +31,8 @@ #include +#include "MEM_guardedalloc.h" + #include "BKE_main.h" #include "BKE_movieclip.h" #include "BKE_context.h" @@ -40,6 +42,8 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "GPU_extensions.h" + #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -47,6 +51,7 @@ #include "ED_clip.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" @@ -314,3 +319,167 @@ void ED_clip_mouse_pos(bContext *C, wmEvent *event, float co[2]) { ED_clip_point_stable_pos(C, event->mval[0], event->mval[1], &co[0], &co[1]); } + +/* OpenGL draw context */ + +typedef struct SpaceClipDrawContext { + int support_checked, buffers_supported; + + GLuint texture; /* OGL texture ID */ + short texture_allocated; /* flag if texture was allocated by glGenTextures */ + struct ImBuf *texture_ibuf; /* image buffer for which texture was created */ + int image_width, image_height; /* image width and height for which texture was created */ + unsigned last_texture; /* ID of previously used texture, so it'll be restored after clip drawing */ + int framenr; +} SpaceClipDrawContext; + +int ED_space_clip_texture_buffer_supported(SpaceClip *sc) +{ + SpaceClipDrawContext *context = sc->draw_context; + + if (!context) { + context = MEM_callocN(sizeof(SpaceClipDrawContext), "SpaceClipDrawContext"); + sc->draw_context = context; + } + + if (!context->support_checked) { + context->support_checked = TRUE; + context->buffers_supported = GPU_non_power_of_two_support(); + } + + return context->buffers_supported; +} + +int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) +{ + SpaceClipDrawContext *context = sc->draw_context; + MovieClip *clip = ED_space_clip(sc); + int need_rebind = 0; + + context->last_texture = glaGetOneInteger(GL_TEXTURE_2D); + + /* image texture need to be rebinded if displaying another image buffer + * assuming displaying happens of footage frames only on which painting doesn't heppen. + * so not changed image buffer pointer means unchanged image content */ + need_rebind |= context->texture_ibuf != ibuf; + need_rebind |= context->framenr != sc->user.framenr; + + if (need_rebind) { + int width = ibuf->x, height = ibuf->y; + float *frect = NULL, *fscalerect = NULL; + unsigned int *rect = NULL, *scalerect = NULL; + int need_recreate = 0; + + if (width > GL_MAX_TEXTURE_SIZE || height > GL_MAX_TEXTURE_SIZE) + return 0; + + rect = ibuf->rect; + frect = ibuf->rect_float; + + /* if image resolution changed (e.g. switched to proxy display) texture need to be recreated */ + need_recreate = context->image_width != ibuf->x || context->image_height != ibuf->y; + + if (context->texture_ibuf && need_recreate) { + glDeleteTextures(1, &context->texture); + context->texture_allocated = 0; + } + +#if 0 + /* disabled for now because current tracking users have got NPOT textures + * working smoothly on their computers and forcing re-scaling during playback + * slows down playback a lot */ + + /* if videocard doesn't support NPOT textures, need to do rescaling */ + if (!GPU_non_power_of_two_support()) { + if (!is_power_of_2_i(width) || !is_power_of_2_i(height)) { + width = power_of_2_max_i(width); + height = power_of_2_max_i(height); + + if (ibuf->x != width || ibuf->y != height) { + if (frect) { + fscalerect= MEM_mallocN(width*width*sizeof(*fscalerect)*4, "fscalerect"); + gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float, width, height, GL_FLOAT, fscalerect); + + frect = fscalerect; + } + else { + scalerect= MEM_mallocN(width*height*sizeof(*scalerect), "scalerect"); + gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect, width, height, GL_UNSIGNED_BYTE, scalerect); + + rect = scalerect; + } + } + } + } +#endif + + if (need_recreate || !context->texture_allocated) { + /* texture doesn't exist yet or need to be re-allocated because of changed dimensions */ + int filter = GL_LINEAR; + + /* non-scaled proxy shouldn;t use diltering */ + if ((clip->flag & MCLIP_USE_PROXY) == 0 || + ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100)) + { + filter = GL_NEAREST; + } + + glGenTextures(1, &context->texture); + glBindTexture(GL_TEXTURE_2D, context->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + } + else { + /* if texture doesn't need to be reallocated itself, just bind it so + * loading of image will happen to a proper texture */ + glBindTexture(GL_TEXTURE_2D, context->texture); + } + + if (frect) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, width, height, 0, GL_RGBA, GL_FLOAT, frect); + else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + + /* store settings */ + context->texture_allocated = 1; + context->texture_ibuf = ibuf; + context->image_width = ibuf->x; + context->image_height = ibuf->y; + context->framenr = sc->user.framenr; + + if (fscalerect) + MEM_freeN(fscalerect); + if (scalerect) + MEM_freeN(scalerect); + } + else { + /* displaying exactly the same image which was loaded t oa texture, + * just bint texture in this case */ + glBindTexture(GL_TEXTURE_2D, context->texture); + } + + glEnable(GL_TEXTURE_2D); + + return 1; +} + +void ED_space_clip_unload_movieclip_buffer(SpaceClip *sc) +{ + SpaceClipDrawContext *context = sc->draw_context; + + glBindTexture(GL_TEXTURE_2D, context->last_texture); + glDisable(GL_TEXTURE_2D); +} + +void ED_space_clip_free_texture_buffer(SpaceClip *sc) +{ + SpaceClipDrawContext *context = sc->draw_context; + + if (context) { + glDeleteTextures(1, &context->texture); + + MEM_freeN(context); + } +} diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 228c716e3b6..60322098250 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -214,6 +214,8 @@ static void clip_free(SpaceLink *sl) if (sc->scopes.track_preview) IMB_freeImBuf(sc->scopes.track_preview); + + ED_space_clip_free_texture_buffer(sc); } /* spacetype; init callback */ @@ -228,7 +230,8 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) /* clear or remove stuff from old */ scn->scopes.track_preview = NULL; - scn->scopes.ok = FALSE; + scn->scopes.ok = 0; + scn->draw_context = NULL; return (SpaceLink *)scn; } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 1938c63d474..958e8b44b9d 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -523,6 +523,7 @@ typedef struct SpaceClip { int postproc_flag; int runtime_flag; /* different runtime flags */ + void *draw_context; } SpaceClip; /* view3d Now in DNA_view3d_types.h */ From ec4edb94d93fe3db7e0e16bdc341cfeabfe6690f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 14 Apr 2012 12:03:23 +0000 Subject: [PATCH 003/183] Camera tracking: initial commit of dopesheet view for clip editor: - Changed regions to use the whole main region for such views as curves and dopesheet. This allows to have own panels with tools/properties in this areas. - Active clip is getting synchronized between different clip editor editors in the same screen, so updating of curve/dopesheet views happens automatically when one changes current clip in one of this editors. - Curves and dopesheet are still using PREVIEW region type instead of re-using main region. - To deal with vertical synchronization in dopesheet, re-initialization of preview region happens. - Panels in toolbox and properties panels are now separated to rely on current view mode, some operators and poll functions still need to be updated. - Added new screen called "Movie Tracking" where layout is configured to display timeline, main clip window, curves and dopesheet. --- release/scripts/startup/bl_ui/space_clip.py | 208 +- .../blender/editors/datafiles/startup.blend.c | 19131 ++++++++-------- source/blender/editors/include/ED_clip.h | 3 +- source/blender/editors/interface/resources.c | 14 + .../blender/editors/space_clip/CMakeLists.txt | 16 +- .../blender/editors/space_clip/clip_buttons.c | 8 + .../editors/space_clip/clip_dopesheet_draw.c | 380 + .../editors/space_clip/clip_dopesheet_ops.c | 166 + .../blender/editors/space_clip/clip_editor.c | 27 +- .../editors/space_clip/clip_graph_draw.c | 58 +- .../editors/space_clip/clip_graph_ops.c | 10 +- .../blender/editors/space_clip/clip_intern.h | 26 + source/blender/editors/space_clip/clip_ops.c | 2 +- .../blender/editors/space_clip/clip_toolbar.c | 8 +- .../blender/editors/space_clip/clip_utils.c | 60 + .../blender/editors/space_clip/space_clip.c | 435 +- source/blender/makesdna/DNA_space_types.h | 5 +- source/blender/makesdna/DNA_tracking_types.h | 1 + source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_space.c | 10 +- source/blender/makesrna/intern/rna_userdef.c | 13 + 21 files changed, 11016 insertions(+), 9566 deletions(-) create mode 100644 source/blender/editors/space_clip/clip_dopesheet_draw.c create mode 100644 source/blender/editors/space_clip/clip_dopesheet_ops.c diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index f83c66dc991..fb84fa29cbc 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -38,19 +38,21 @@ class CLIP_HT_header(Header): sub = row.row(align=True) sub.menu("CLIP_MT_view") - if clip: - sub.menu("CLIP_MT_select") + if sc.view == 'CLIP': + if clip: + sub.menu("CLIP_MT_select") - sub.menu("CLIP_MT_clip") + sub.menu("CLIP_MT_clip") - if clip: - sub.menu("CLIP_MT_track") - sub.menu("CLIP_MT_reconstruction") + if clip: + sub.menu("CLIP_MT_track") + sub.menu("CLIP_MT_reconstruction") + + layout.prop(sc, "view", text="", expand=True) if clip: - layout.prop(sc, "mode", text="") - layout.prop(sc, "view", text="", expand=True) - + if sc.view == 'CLIP': + layout.prop(sc, "mode", text="") if sc.view == 'GRAPH': row = layout.row(align=True) @@ -79,24 +81,56 @@ class CLIP_HT_header(Header): else: r = tracking.reconstruction - if r.is_valid: + if r.is_valid and sc.view == 'CLIP': layout.label(text="Average solve error: %.4f" % (r.average_error)) layout.template_running_jobs() -class CLIP_PT_tools_marker(Panel): - bl_space_type = 'CLIP_EDITOR' - bl_region_type = 'TOOLS' - bl_label = "Marker" +class CLIP_PT_clip_view_panel: @classmethod def poll(cls, context): sc = context.space_data clip = sc.clip - return clip and sc.mode == 'TRACKING' + return clip and sc.view == 'CLIP' + +class CLIP_PT_tracking_panel: + + @classmethod + def poll(cls, context): + sc = context.space_data + clip = sc.clip + + return clip and sc.mode == 'TRACKING' and sc.view == 'CLIP' + + +class CLIP_PT_reconstruction_panel: + + @classmethod + def poll(cls, context): + sc = context.space_data + clip = sc.clip + + return clip and sc.mode == 'RECONSTRUCTION' and sc.view == 'CLIP' + + +class CLIP_PT_distortion_panel: + + @classmethod + def poll(cls, context): + sc = context.space_data + clip = sc.clip + + return clip and sc.mode == 'DISTORTION' and sc.view == 'CLIP' + + +class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'TOOLS' + bl_label = "Marker" def draw(self, context): sc = context.space_data @@ -162,18 +196,11 @@ class CLIP_PT_tools_marker(Panel): text="Copy From Active Track") -class CLIP_PT_tools_tracking(Panel): +class CLIP_PT_tools_tracking(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Track" - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return clip and sc.mode == 'TRACKING' - def draw(self, context): layout = self.layout @@ -201,18 +228,11 @@ class CLIP_PT_tools_tracking(Panel): layout.operator("clip.join_tracks", text="Join") -class CLIP_PT_tools_solve(Panel): +class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Solve" - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return clip and sc.mode == 'TRACKING' - def draw(self, context): layout = self.layout clip = context.space_data.clip @@ -241,18 +261,11 @@ class CLIP_PT_tools_solve(Panel): col.prop(settings, "refine_intrinsics", text="") -class CLIP_PT_tools_cleanup(Panel): +class CLIP_PT_tools_cleanup(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Clean up" - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return clip and sc.mode == 'TRACKING' - def draw(self, context): layout = self.layout clip = context.space_data.clip @@ -265,18 +278,11 @@ class CLIP_PT_tools_cleanup(Panel): layout.prop(settings, 'clean_action', text="") -class CLIP_PT_tools_geometry(Panel): +class CLIP_PT_tools_geometry(CLIP_PT_reconstruction_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Geometry" - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return clip and sc.mode == 'RECONSTRUCTION' - def draw(self, context): layout = self.layout @@ -284,18 +290,11 @@ class CLIP_PT_tools_geometry(Panel): layout.operator("clip.track_to_empty") -class CLIP_PT_tools_orientation(Panel): +class CLIP_PT_tools_orientation(CLIP_PT_reconstruction_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Orientation" - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return clip and sc.mode == 'RECONSTRUCTION' - def draw(self, context): sc = context.space_data layout = self.layout @@ -320,18 +319,19 @@ class CLIP_PT_tools_orientation(Panel): col.prop(settings, "distance") -class CLIP_PT_tools_object(Panel): +class CLIP_PT_tools_object(CLIP_PT_reconstruction_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Object" @classmethod def poll(cls, context): - sc = context.space_data - clip = sc.clip + if CLIP_PT_reconstruction_panel.poll(context): + sc = context.space_data + clip = sc.clip - if clip and sc.mode == 'RECONSTRUCTION': tracking_object = clip.tracking.objects.active + return not tracking_object.is_camera return False @@ -354,18 +354,11 @@ class CLIP_PT_tools_object(Panel): col.prop(settings, "object_distance") -class CLIP_PT_tools_grease_pencil(Panel): +class CLIP_PT_tools_grease_pencil(CLIP_PT_distortion_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Grease Pencil" - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return clip and sc.mode == 'DISTORTION' - def draw(self, context): layout = self.layout @@ -383,18 +376,12 @@ class CLIP_PT_tools_grease_pencil(Panel): row.prop(context.tool_settings, "use_grease_pencil_sessions") -class CLIP_PT_objects(Panel): +class CLIP_PT_objects(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Objects" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - sc = context.space_data - - return sc.clip - def draw(self, context): layout = self.layout @@ -415,18 +402,11 @@ class CLIP_PT_objects(Panel): layout.prop(active, "name") -class CLIP_PT_track(Panel): +class CLIP_PT_track(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Track" - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return sc.mode == 'TRACKING' and clip - def draw(self, context): layout = self.layout sc = context.space_data @@ -482,18 +462,12 @@ class CLIP_PT_track(Panel): layout.label(text=label_text) -class CLIP_PT_track_settings(Panel): +class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Tracking Settings" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - sc = context.space_data - - return sc.mode == 'TRACKING' and sc.clip - def draw(self, context): layout = self.layout clip = context.space_data.clip @@ -525,9 +499,12 @@ class CLIP_PT_tracking_camera(Panel): @classmethod def poll(cls, context): - sc = context.space_data + if CLIP_PT_clip_view_panel.poll(context): + sc = context.space_data - return sc.mode in {'TRACKING', 'DISTORTION'} and sc.clip + return sc.mode in {'TRACKING', 'DISTORTION'} and sc.clip + + return False def draw(self, context): layout = self.layout @@ -568,7 +545,7 @@ class CLIP_PT_tracking_camera(Panel): col.prop(clip.tracking.camera, "k3") -class CLIP_PT_display(Panel): +class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Display" @@ -613,7 +590,7 @@ class CLIP_PT_display(Panel): row.prop(clip, "display_aspect", text="") -class CLIP_PT_marker_display(Panel): +class CLIP_PT_marker_display(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Marker Display" @@ -636,18 +613,12 @@ class CLIP_PT_marker_display(Panel): row.prop(sc, "path_length", text="Length") -class CLIP_PT_stabilization(Panel): +class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "2D Stabilization" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - sc = context.space_data - - return sc.mode == 'RECONSTRUCTION' and sc.clip - def draw_header(self, context): stab = context.space_data.clip.tracking.stabilization @@ -695,19 +666,12 @@ class CLIP_PT_stabilization(Panel): layout.prop(stab, "filter_type") -class CLIP_PT_marker(Panel): +class CLIP_PT_marker(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Marker" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return sc.mode == 'TRACKING' and clip - def draw(self, context): layout = self.layout sc = context.space_data @@ -721,18 +685,12 @@ class CLIP_PT_marker(Panel): layout.label(text="No active track") -class CLIP_PT_proxy(Panel): +class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Proxy / Timecode" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - sc = context.space_data - - return sc.clip - def draw_header(self, context): sc = context.space_data @@ -782,18 +740,12 @@ class CLIP_PT_proxy(Panel): col.prop(sc.clip_user, "use_render_undistorted") -class CLIP_PT_footage(Panel): +class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Footage Settings" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - sc = context.space_data - - return sc.clip - def draw(self, context): layout = self.layout @@ -806,17 +758,11 @@ class CLIP_PT_footage(Panel): layout.operator("clip.open", icon='FILESEL') -class CLIP_PT_tools_clip(Panel): +class CLIP_PT_tools_clip(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Clip" - @classmethod - def poll(cls, context): - sc = context.space_data - - return sc.clip - def draw(self, context): layout = self.layout @@ -829,6 +775,10 @@ class CLIP_MT_view(Menu): def draw(self, context): layout = self.layout + sc = context.space_data + + layout.prop(sc, "show_seconds") + layout.separator() layout.operator("clip.properties", icon='MENU_PANEL') layout.operator("clip.tools", icon='MENU_PANEL') diff --git a/source/blender/editors/datafiles/startup.blend.c b/source/blender/editors/datafiles/startup.blend.c index 177fe320ed7..f2ea7d8bbd5 100644 --- a/source/blender/editors/datafiles/startup.blend.c +++ b/source/blender/editors/datafiles/startup.blend.c @@ -1,12 +1,12 @@ /* DataToC output of file */ -int datatoc_startup_blend_size= 358796; -char datatoc_startup_blend[]= { - 66, 76, 69, 78, 68, 69, 82, 45,118, 50, 54, 50, - 82, 69, 78, 68, 32, 0, 0, 0, 56,211, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, - 83, 99,101,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 76, 79, 66, 48, 4, 0, 0, -224,206, 35, 0, 0, 0, 0, 0,216, 0, 0, 0, 1, 0, 0, 0, 32, 32, 32, 51, 3, 0, 0, 0,250, 0, 0, 0, 1, 0, 0, 1, -248, 9,215, 3, 0, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 0, 16, 0, 0,128, 32, 4, 0,126,176, 0, 0, 0, 0, 0, 0, +int datatoc_startup_blend_size = 375344; +char datatoc_startup_blend[] = { + 66, 76, 69, 78, 68, 69, 82, 45,118, 50, 54, 50, 82, 69, 78, 68, + 32, 0, 0, 0, 64,202, 23,183,255,127, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 83, 99,101,110, +101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 76, 79, 66, 48, 4, 0, 0, 48,198, 23,183, +255,127, 0, 0,216, 0, 0, 0, 1, 0, 0, 0, 32, 32, 32, 51, 3, 0, 0, 0,250, 0, 0, 0, 1, 0, 0, 1,248,163,195, 6, + 0, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 16, 0, 0,128, 32, 4, 0, 53,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -38,5102 +38,133 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 87, 77, 0, 0, 88, 1, 0, 0, 8, 78,210, 3, 0, 0, 0, 0,146, 1, 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, 87, 77, 87,105,110, 77, 97,110, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,122,199, 3, 0, 0, 0, 0, 56,122,199, 3, 0, 0, 0, 0, - 56,122,199, 3, 0, 0, 0, 0, 56,122,199, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,232, 89,178, 3, 0, 0, 0, 0, -120, 93,178, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 60,171, 3, 0, 0, 0, 0, -104,164,152, 15, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 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,120, 58,171, 3, 0, 0, 0, 0,120, 58,171, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 86,178, 3, 0, 0, 0, 0,184, 88,178, 3, 0, 0, 0, 0, - 88, 86,178, 3, 0, 0, 0, 0,136, 87,178, 3, 0, 0, 0, 0,184, 88,178, 3, 0, 0, 0, 0,232,255,210, 3, 0, 0, 0, 0, -232,255,210, 3, 0, 0, 0, 0,232,255,210, 3, 0, 0, 0, 0, 68, 65, 84, 65, 0, 1, 0, 0, 56,122,199, 3, 0, 0, 0, 0, -147, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93,198, 3, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0,248, 9,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115, 99,114,101,101,110, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 0, 70, 5,178, 2, - 0, 0, 0, 0, 1, 0,238, 3, 0, 0, 0, 0, 1, 0, 0, 0,152,127,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,136, 39,205, 15, 0, 0, 0, 0,152, 0,212, 15, 0, 0, 0, 0, -168,255,211, 15, 0, 0, 0, 0,104, 12,163, 3, 0, 0, 0, 0, 56, 9,163, 3, 0, 0, 0, 0, 88, 11,163, 3, 0, 0, 0, 0, - 88, 11,163, 3, 0, 0, 0, 0,152, 84,171, 3, 0, 0, 0, 0,120,149,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 78, 0, 0, 8, 1, 0, 0,136, 7,214, 3, 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0, - 8,156,214, 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, - 83, 82, 65,110,105,109, 97,116,105,111,110, 0, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 9,201, 3, 0, 0, 0, 0, - 72, 20,201, 3, 0, 0, 0, 0,184, 88,171, 3, 0, 0, 0, 0,248,107,171, 3, 0, 0, 0, 0, 24, 9,214, 3, 0, 0, 0, 0, -248,150,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 32, 0, 0, 0,168, 9,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, - 72, 10,201, 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, - 68, 65, 84, 65, 32, 0, 0, 0, 72, 10,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232, 10,201, 3, 0, 0, 0, 0, -168, 9,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,222, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -232, 10,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136, 11,201, 3, 0, 0, 0, 0, 72, 10,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,240, 4,222, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,136, 11,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0, 40, 12,201, 3, 0, 0, 0, 0,232, 10,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 4, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 40, 12,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -200, 12,201, 3, 0, 0, 0, 0,136, 11,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195, 2, 1, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0,200, 12,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104, 13,201, 3, 0, 0, 0, 0, - 40, 12,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -104, 13,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8, 14,201, 3, 0, 0, 0, 0,200, 12,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8, 14,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0,168, 14,201, 3, 0, 0, 0, 0,104, 13,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 24, 4,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,168, 14,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, - 72, 15,201, 3, 0, 0, 0, 0, 8, 14,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 60, 1, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0, 72, 15,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232, 15,201, 3, 0, 0, 0, 0, -168, 14,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 60, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -232, 15,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136, 16,201, 3, 0, 0, 0, 0, 72, 15,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,136, 16,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0, 40, 17,201, 3, 0, 0, 0, 0,232, 15,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 24, 4, 88, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 40, 17,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -200, 17,201, 3, 0, 0, 0, 0,136, 16,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 1, 88, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0,200, 17,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104, 18,201, 3, 0, 0, 0, 0, - 40, 17,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 1,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -104, 18,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8, 19,201, 3, 0, 0, 0, 0,200, 17,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8, 19,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0,168, 19,201, 3, 0, 0, 0, 0,104, 18,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -192, 1, 4, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,168, 19,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, - 72, 20,201, 3, 0, 0, 0, 0, 8, 19,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 60, 2, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0, 72, 20,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -168, 19,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 60, 2, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -184, 88,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104, 89,171, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 72, 10,201, 3, 0, 0, 0, 0,232, 10,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -104, 89,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24, 90,171, 3, 0, 0, 0, 0,184, 88,171, 3, 0, 0, 0, 0, - 72, 10,201, 3, 0, 0, 0, 0, 40, 12,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 24, 90,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200, 90,171, 3, 0, 0, 0, 0,104, 89,171, 3, 0, 0, 0, 0, -232, 10,201, 3, 0, 0, 0, 0,200, 12,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -200, 90,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120, 91,171, 3, 0, 0, 0, 0, 24, 90,171, 3, 0, 0, 0, 0, - 40, 12,201, 3, 0, 0, 0, 0,200, 12,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -120, 91,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40, 92,171, 3, 0, 0, 0, 0,200, 90,171, 3, 0, 0, 0, 0, -168, 9,201, 3, 0, 0, 0, 0,104, 13,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 40, 92,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216, 92,171, 3, 0, 0, 0, 0,120, 91,171, 3, 0, 0, 0, 0, -136, 11,201, 3, 0, 0, 0, 0,104, 13,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -216, 92,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136, 93,171, 3, 0, 0, 0, 0, 40, 92,171, 3, 0, 0, 0, 0, -200, 12,201, 3, 0, 0, 0, 0, 8, 14,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -136, 93,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56, 94,171, 3, 0, 0, 0, 0,216, 92,171, 3, 0, 0, 0, 0, -104, 13,201, 3, 0, 0, 0, 0,168, 14,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 56, 94,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232, 94,171, 3, 0, 0, 0, 0,136, 93,171, 3, 0, 0, 0, 0, -136, 11,201, 3, 0, 0, 0, 0, 72, 15,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -232, 94,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152, 95,171, 3, 0, 0, 0, 0, 56, 94,171, 3, 0, 0, 0, 0, -168, 14,201, 3, 0, 0, 0, 0, 72, 15,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -152, 95,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72, 96,171, 3, 0, 0, 0, 0,232, 94,171, 3, 0, 0, 0, 0, -168, 9,201, 3, 0, 0, 0, 0,232, 15,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 72, 96,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248, 96,171, 3, 0, 0, 0, 0,152, 95,171, 3, 0, 0, 0, 0, - 8, 14,201, 3, 0, 0, 0, 0,136, 16,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -248, 96,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168, 97,171, 3, 0, 0, 0, 0, 72, 96,171, 3, 0, 0, 0, 0, -104, 13,201, 3, 0, 0, 0, 0,136, 16,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -168, 97,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88, 98,171, 3, 0, 0, 0, 0,248, 96,171, 3, 0, 0, 0, 0, -232, 15,201, 3, 0, 0, 0, 0,136, 16,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 88, 98,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8, 99,171, 3, 0, 0, 0, 0,168, 97,171, 3, 0, 0, 0, 0, -232, 15,201, 3, 0, 0, 0, 0, 40, 17,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 8, 99,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184, 99,171, 3, 0, 0, 0, 0, 88, 98,171, 3, 0, 0, 0, 0, -136, 16,201, 3, 0, 0, 0, 0, 40, 17,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -184, 99,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104,100,171, 3, 0, 0, 0, 0, 8, 99,171, 3, 0, 0, 0, 0, - 40, 12,201, 3, 0, 0, 0, 0,200, 17,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -104,100,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24,101,171, 3, 0, 0, 0, 0,184, 99,171, 3, 0, 0, 0, 0, - 8, 14,201, 3, 0, 0, 0, 0,200, 17,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 24,101,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200,101,171, 3, 0, 0, 0, 0,104,100,171, 3, 0, 0, 0, 0, - 40, 17,201, 3, 0, 0, 0, 0,200, 17,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -200,101,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120,102,171, 3, 0, 0, 0, 0, 24,101,171, 3, 0, 0, 0, 0, -232, 15,201, 3, 0, 0, 0, 0,104, 18,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -120,102,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40,103,171, 3, 0, 0, 0, 0,200,101,171, 3, 0, 0, 0, 0, - 40, 17,201, 3, 0, 0, 0, 0, 8, 19,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 40,103,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216,103,171, 3, 0, 0, 0, 0,120,102,171, 3, 0, 0, 0, 0, -104, 18,201, 3, 0, 0, 0, 0, 8, 19,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -216,103,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136,104,171, 3, 0, 0, 0, 0, 40,103,171, 3, 0, 0, 0, 0, -168, 14,201, 3, 0, 0, 0, 0,168, 19,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -136,104,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56,105,171, 3, 0, 0, 0, 0,216,103,171, 3, 0, 0, 0, 0, - 8, 14,201, 3, 0, 0, 0, 0,168, 19,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 56,105,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232,105,171, 3, 0, 0, 0, 0,136,104,171, 3, 0, 0, 0, 0, -200, 12,201, 3, 0, 0, 0, 0, 72, 20,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -232,105,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152,106,171, 3, 0, 0, 0, 0, 56,105,171, 3, 0, 0, 0, 0, - 72, 15,201, 3, 0, 0, 0, 0, 72, 20,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -152,106,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72,107,171, 3, 0, 0, 0, 0,232,105,171, 3, 0, 0, 0, 0, -168, 19,201, 3, 0, 0, 0, 0, 72, 20,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 72,107,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248,107,171, 3, 0, 0, 0, 0,152,106,171, 3, 0, 0, 0, 0, - 40, 12,201, 3, 0, 0, 0, 0,104, 18,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -248,107,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,107,171, 3, 0, 0, 0, 0, -200, 17,201, 3, 0, 0, 0, 0, 8, 19,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, - 24, 9,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 56, 10,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 40, 12,201, 3, 0, 0, 0, 0, 72, 10,201, 3, 0, 0, 0, 0,232, 10,201, 3, 0, 0, 0, 0,200, 12,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0,196, 2, 0, 0,222, 2, 0, 0, 7, 7,241, 4, 27, 0, 1, 0, - 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,197,207, 3, 0, 0, 0, 0,152,197,207, 3, 0, 0, 0, 0, -136,221,175, 3, 0, 0, 0, 0, 56,223,175, 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, 68, 65, 84, 65, 40, 1, 0, 0,136,221,175, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 56,223,175, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,148, 68, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 32,158, 68, 0, 0, 0, 0, 0, 0,208, 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,240, 4, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0, 0,158, 68, 0, 0,200, 65, 0, 0,158, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,241, 4, 26, 0,241, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0,196, 2, 0, 0,221, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,241, 4, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56,223,175, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,221,175, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,109, 69, - 0, 0,128,192, 0, 0, 0, 0, 0, 0, 0, 0,255,255,109, 69, 0, 0, 0,192, 0, 0, 0, 0,112, 7, 0, 0,129, 7, 0, 0, - 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, - 18, 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,128, 63, 0, 0,128, 63, - 2, 0, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,129, 7, 2, 0,112, 7, 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,222, 2, 0, 0,222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65,160, 0, 0, 0, 56, 10,214, 3, 0, 0, 0, 0, -214, 0, 0, 0, 1, 0, 0, 0, 88, 11,214, 3, 0, 0, 0, 0, 24, 9,214, 3, 0, 0, 0, 0,104, 13,201, 3, 0, 0, 0, 0, -168, 14,201, 3, 0, 0, 0, 0, 72, 15,201, 3, 0, 0, 0, 0,136, 11,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 4, 0, 0,240, 4, 0, 0, 0, 0, 0, 0, 59, 1, 0, 0, 4, 4,216, 0, 60, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,184,123,199, 3, 0, 0, 0, 0,184,123,199, 3, 0, 0, 0, 0,232,224,175, 3, 0, 0, 0, 0, -152,226,175, 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, 68, 65, 84, 65, 40, 1, 0, 0,232,224,175, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, -152,226,175, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148, 67, 0, 0, 0, 0, 0, 0,208, 65, - 98, 39, 38, 54, 0, 0, 88, 67, 0, 0, 0, 0, 0, 0,208, 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,215, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, - 0, 0, 87, 67, 0, 0,200, 65, 0, 0, 87, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, - 4, 0, 12, 0, 10, 0,216, 0, 26, 0,216, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 4, 0, 0,240, 4, 0, 0, 34, 1, 0, 0, 59, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -216, 0, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,152,226,175, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,232,224,175, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 67, 0, 0, 61,196, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 71, 67, 1, 0,145,195, 0, 0, 0, 0,199, 0, 0, 0,216, 0, 0, 0, 0, 0, 0, 0, 33, 1, 0, 0, - 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,198, 0, 0, 0, 0, 0, 0, 0, 33, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, - 18, 0, 0, 4, 6, 0,216, 0, 34, 1,199, 0, 34, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 4, 0, 0,240, 4, 0, 0, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -216, 0, 34, 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, 56, 51,214, 3, 0, 0, 0, 0, -216, 71,214, 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, 68, 65, 84, 65, 88, 1, 0, 0, 56, 51,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, - 24, 53,214, 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, - 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, - 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, - 67,111,110,116,101,120,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,220,255,199, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, - 24, 53,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,248, 54,214, 3, 0, 0, 0, 0, 56, 51,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255,199, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 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, 68, 65, 84, 65, 88, 1, 0, 0,248, 54,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, -216, 56,214, 3, 0, 0, 0, 0, 24, 53,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,255,199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, -216, 56,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,184, 58,214, 3, 0, 0, 0, 0,248, 54,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115, -105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115, -105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140,254,199, 0,203, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,184, 58,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, -152, 60,214, 3, 0, 0, 0, 0,216, 56,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 65,110,116,105, 45, 65,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 58,254,199, 0, 58, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, -152, 60,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,120, 62,214, 3, 0, 0, 0, 0,184, 58,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, - 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, - 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97,109,112,108,101,100, 32, 77,111,116,105,111,110, 32, 66, -108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,254,199, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,120, 62,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, - 88, 64,214, 3, 0, 0, 0, 0,152, 60,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 83,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 10,254,199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, - 88, 64,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 56, 66,214, 3, 0, 0, 0, 0,120, 62,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114, -109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114, -109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,242,253,199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 56, 66,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, - 24, 68,214, 3, 0, 0, 0, 0, 88, 64,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80,111,115,116, 32, 80,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,218,253,199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, - 24, 68,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,248, 69,214, 3, 0, 0, 0, 0, 56, 66,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194,253,199, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,248, 69,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, -216, 71,214, 3, 0, 0, 0, 0, 24, 68,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, - 79,117,116,112,117,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, 40,253,199, 0,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, -216, 71,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 69,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,253,199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,184,123,199, 3, 0, 0, 0, 0,179, 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, - 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, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -255, 21, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, - 88, 11,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,120, 12,214, 3, 0, 0, 0, 0, 56, 10,214, 3, 0, 0, 0, 0, -168, 9,201, 3, 0, 0, 0, 0,232, 15,201, 3, 0, 0, 0, 0,136, 16,201, 3, 0, 0, 0, 0,104, 13,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 15, 15, 24, 4, 88, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 92,200, 3, 0, 0, 0, 0,216, 92,200, 3, 0, 0, 0, 0, - 72,228,175, 3, 0, 0, 0, 0,248,229,175, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72,228,175, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,248,229,175, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,140, 68, - 0, 0, 0, 0, 0, 0,208, 65, 39,182,158, 55, 0, 0,131, 68, 0, 0, 0, 0, 0, 0,208, 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, 23, 4, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0,224,130, 68, 0, 0,200, 65, 0,224,130, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 24, 4, 26, 0, 24, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,248,229,175, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,228,175, 3, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, - 0, 0, 0, 0, 0, 0, 72, 66,112,189, 17,192,246, 70,125, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, - 18, 0, 0, 0, 61, 0, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, - 72, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 4, 8, 0, 24, 4, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 26, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,208, 0, 0, 0,216, 92,200, 3, 0, 0, 0, 0, -190, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, -120, 12,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 40, 14,214, 3, 0, 0, 0, 0, 88, 11,214, 3, 0, 0, 0, 0, -168, 14,201, 3, 0, 0, 0, 0,168, 19,201, 3, 0, 0, 0, 0, 72, 20,201, 3, 0, 0, 0, 0, 72, 15,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 61, 1, 0, 0, 59, 2, 0, 0, 3, 3,216, 0,255, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,255,208, 3, 0, 0, 0, 0, 40,255,208, 3, 0, 0, 0, 0, -168,231,175, 3, 0, 0, 0, 0, 88,233,175, 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, 68, 65, 84, 65, 40, 1, 0, 0,168,231,175, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 88,233,175, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,244, 67, - 0, 0, 0, 0, 0, 0,208, 65, 98, 39, 38, 54, 0, 0, 88, 67, 0, 0, 0, 0, 0, 0,208, 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,215, 0, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 87, 67, 0, 0,200, 65, 0, 0, 87, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,216, 0, 26, 0,216, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 34, 2, 0, 0, 59, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,216, 0, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 88,233,175, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,231,175, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,141, 67, - 0, 0,244,194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 67, 0, 0, 83,195, 0, 0, 0, 0,199, 0, 0, 0,216, 0, 0, 0, - 18, 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0,198, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,198, 0, 0, 0, - 18, 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 18, 2, 0, 0, 2, 0, 3, 3, 0, 0, 12, 4, 6, 0,216, 0,229, 0,199, 0,211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 61, 1, 0, 0, 33, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,216, 0,229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 1, 0, 0, 40,255,208, 3, 0, 0, 0, 0, -183, 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, 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, -152, 13,214, 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, 1, 0, 0, 0, - 68, 65, 84, 65, 16, 0, 0, 0,152, 13,214, 3, 0, 0, 0, 0,237, 0, 0, 0, 1, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, -248, 30,199, 3, 0, 0, 0, 0, 68, 65, 84, 65,224, 0, 0, 0,248, 30,199, 3, 0, 0, 0, 0,236, 0, 0, 0, 14, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 19, 0, 0, 0, 1, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, - 20, 0, 0, 0, 1, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 21, 0, 1, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 0, 24, 51,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,184,219,217, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 0,136, 48,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,152, 7,218, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 0,216, 29,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,168,225,217, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 0,120,209,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,200,213,217, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 0, 24, 98,200, 3, 0, 0, 0, 0, 21, 0, 0, 0, 1, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, - 68, 65, 84, 65,160, 0, 0, 0, 40, 14,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 72, 15,214, 3, 0, 0, 0, 0, -120, 12,214, 3, 0, 0, 0, 0, 40, 17,201, 3, 0, 0, 0, 0,200, 17,201, 3, 0, 0, 0, 0, 8, 14,201, 3, 0, 0, 0, 0, -136, 16,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 1, 0, 0, 23, 4, 0, 0, 89, 0, 0, 0,194, 2, 0, 0, - 1, 1, 87, 2,106, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184, 73,214, 3, 0, 0, 0, 0, -184, 73,214, 3, 0, 0, 0, 0, 8,235,175, 3, 0, 0, 0, 0, 72, 88,214, 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, 68, 65, 84, 65, 40, 1, 0, 0, - 8,235,175, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 56, 83,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 64,113, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,192, 21, 68, 0, 0, 0, 0, 0, 0,208, 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, 86, 2, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128, 21, 68, 0, 0,200, 65, 0,128, 21, 68, 0, 0,200, 65, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 87, 2, 26, 0, 87, 2, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 1, 0, 0, 23, 4, 0, 0, 89, 0, 0, 0,114, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 2, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, - 56, 83,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,232, 84,214, 3, 0, 0, 0, 0, 8,235,175, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 15, 67, 0, 64, 70,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67,255,127, 70,196, 0, 0, 0, 0, -143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0, 44, 3,143, 0, 26, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 1, 0, 0,193, 1, 0, 0,115, 0, 0, 0,194, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 80, 2, 0, 0, 5, 0, 3, 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, 68, 65, 84, 65, 40, 1, 0, 0, -232, 84,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,152, 86,214, 3, 0, 0, 0, 0, 56, 83,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 16, 67, 0, 0,206,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, 0, 0,206,194, 0, 0, 0, 0, -143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0,102, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 1, 0, 0,193, 1, 0, 0,115, 0, 0, 0,115, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 6, 0, 34, 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, 68, 65, 84, 65, 40, 1, 0, 0, -152, 86,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 72, 88,214, 3, 0, 0, 0, 0,232, 84,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 35, 67, 0,128, 96,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0,128, 96,196, 0, 0, 0, 0, -163, 0, 0, 0,180, 0, 0, 0, 18, 0, 0, 0,147, 3, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0,162, 0, 0, 0, 18, 0, 0, 0,147, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,180, 0,148, 3,163, 0,130, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 23, 4, 0, 0,115, 0, 0, 0,194, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0, - 72, 88,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 86,214, 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,193, 1, 0, 0, 23, 4, 0, 0,115, 0, 0, 0,194, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 2, 80, 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, 8,115,214, 3, 0, 0, 0, 0, 68, 65, 84, 65,112, 3, 0, 0, - 8,115,214, 3, 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,200,167,141, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 13,128,191, 0, 0,128,191, - 0, 0, 0, 0, 0, 0, 0, 0, 74,215, 76,190, 0, 0, 0, 0, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, 0, 0, 0, 0, - 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,214,211,111,193, 0, 0,128, 63, 69,239,209, 62, 70,119,105, 63,176, 84, 89,188, 0, 0, 0, 0, - 53,177,205,190,142, 74, 70, 62,166, 33,101, 63, 0, 0, 0, 0,185,158, 81, 63, 35, 44,185,190, 43, 61,228, 62, 0, 0, 0, 0, -164, 96, 68, 65,111,121,173,192,248,209,213, 64, 0, 0,128, 63,178,157,229, 62,209,162,227,190, 48,180, 81,191,184,158, 81,191, -117, 90,127, 63, 13,114, 91, 62, 26, 63,185, 62, 35, 44,185, 62,145,180,109,188,105,147,125, 63,138, 84,228,190, 42, 61,228,190, - 0, 0, 0, 0, 0, 0, 0, 0, 9,185,108, 65,214,211,111, 65, 99,240,191, 62,110,116, 85, 63, 64,185, 70,188, 0, 0, 82,180, - 48,221,185,190, 44, 45, 51, 62, 28, 11, 79, 63, 0, 0, 56,179, 67,108,117,194,183,204,216, 65,105,156, 5,194,212,247,159,192, -235, 62,114, 66, 59,254,213,193,158,225, 3, 66, 55, 8,160, 64, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, 0, 0, 0, 0, - 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,214,211,111,193, 0, 0,128, 63,178,157,229, 62,209,162,227,190, 48,180, 81,191,184,158, 81,191, -117, 90,127, 63, 13,114, 91, 62, 26, 63,185, 62, 35, 44,185, 62,145,180,109,188,105,147,125, 63,138, 84,228,190, 42, 61,228,190, - 0, 0, 0, 0, 0, 0, 0, 0, 9,185,108, 65,214,211,111, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,163, 91, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 12,163, 91, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,163, 91, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, 3,236,234,190, -214,211,111, 65,214,211,111, 65, 0, 0, 0, 0, 0, 0, 0, 0,236, 15, 72, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 32, 33, 12, 66, 86,152,137, 66,113, 27,126, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 96, 1, 0, 0,184, 73,214, 3, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, 51, 51, 51, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32, 65,205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200,213,217, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, 8, 8,128, 0, 0, 0, 12, 66, - 0, 0,128, 63,205,204,204, 61, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 16, 0, 10, 0, 7, 1, 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, 68, 65, 84, 65,160, 0, 0, 0, - 72, 15,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,104, 16,214, 3, 0, 0, 0, 0, 40, 14,214, 3, 0, 0, 0, 0, -232, 15,201, 3, 0, 0, 0, 0,104, 18,201, 3, 0, 0, 0, 0, 8, 19,201, 3, 0, 0, 0, 0, 40, 17,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 1, 0, 0, 89, 0, 0, 0, 3, 1, 0, 0, 2, 2,192, 1,171, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,149,199, 3, 0, 0, 0, 0, 8,149,199, 3, 0, 0, 0, 0, -248, 89,214, 3, 0, 0, 0, 0, 8, 95,214, 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, 68, 65, 84, 65, 40, 1, 0, 0,248, 89,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,168, 91,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 89, 68, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,224, 67, 0, 0, 0, 0, 0, 0,208, 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,191, 1, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0,128,223, 67, 0, 0,200, 65, 0,128,223, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,192, 1, 26, 0,192, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 1, 0, 0, 89, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,192, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,168, 91,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 88, 93,214, 3, 0, 0, 0, 0,248, 89,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 67, - 0, 0,112,193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 67, 0, 0,254,194, 0, 0, 0, 0,200, 0, 0, 0,217, 0, 0, 0, - 18, 0, 0, 0,144, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, - 18, 0, 0, 0,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 10, 6, 0, 0, 2, 0, 3, 3, 0, 0, 0, 4, 6, 0,217, 0,145, 0,200, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 0, 0, 0,115, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,217, 0,145, 0, 0, 0, 2, 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, 68, 65, 84, 65, 40, 1, 0, 0, 88, 93,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 8, 95,214, 3, 0, 0, 0, 0,168, 91,214, 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,191, 1, 0, 0,191, 1, 0, 0,115, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8, 95,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 93,214, 3, 0, 0, 0, 0, 0, 0, 16,193, 0, 0,130, 67, - 0, 0,160,192, 0, 0,160, 64, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 16,193, 0, 0, 32, 65, 0, 0, 0, 0, 17, 0, 0, 0, - 18, 0, 0, 0,144, 0, 0, 0, 18, 0, 0, 0,230, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0,230, 0, 0, 0, - 18, 0, 0, 0,144, 0, 0, 0,111, 18,131, 58,111, 18,131, 58, 0,124,146, 72, 0, 80, 67, 71, 0, 0, 0, 0, 0, 0, 0, 0, -105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0,231, 0,145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,217, 0, 0, 0,191, 1, 0, 0,115, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,231, 0,145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,240, 0, 0, 0, 8,149,199, 3, 0, 0, 0, 0, -178, 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, 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, 40,119,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,112, 0, 0, 0, - 40,119,214, 3, 0, 0, 0, 0, 37, 1, 0, 0, 1, 0, 0, 0,168,194,217, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,160, 0, 0, 0,104, 16,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,248,150,214, 3, 0, 0, 0, 0, - 72, 15,214, 3, 0, 0, 0, 0,104, 18,201, 3, 0, 0, 0, 0, 40, 12,201, 3, 0, 0, 0, 0,200, 17,201, 3, 0, 0, 0, 0, - 8, 19,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 1, 0, 0, 5, 1, 0, 0,194, 2, 0, 0, - 12, 12,192, 1,190, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,230,208, 3, 0, 0, 0, 0, -200,230,208, 3, 0, 0, 0, 0,184, 96,214, 3, 0, 0, 0, 0, 24,100,214, 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, 68, 65, 84, 65, 40, 1, 0, 0, -184, 96,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,104, 98,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,192, 94, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,224, 67, 0, 0, 0, 0, 0, 0,208, 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,191, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,223, 67, 0, 0,200, 65, 0,128,223, 67, 0, 0,200, 65, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,192, 1, 26, 0,192, 1, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 1, 0, 0, 5, 1, 0, 0, 30, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, -104, 98,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 24,100,214, 3, 0, 0, 0, 0,184, 96,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 55, 67, 0, 0, 0,194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 67, 0, 0,201,195, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0,199, 0, 0, 0, 18, 0, 0, 0,163, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 8, 4, 0, 0, 2, 0, 3, 3, 0, 0, 2, 4, 6, 0,200, 0,164, 1,200, 0,146, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, 31, 1, 0, 0,194, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 0,164, 1, 0, 0, 2, 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, 68, 65, 84, 65, 40, 1, 0, 0, - 24,100,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 98,214, 3, 0, 0, 0, 0, - 0, 0, 32,193, 0, 0,104, 68, 0, 0, 72,194, 0, 0, 0, 0, 0, 0, 32,193, 0, 0,104, 68, 0, 0,201,195, 0, 0, 0, 0, -231, 0, 0, 0,248, 0, 0, 0, 18, 0, 0, 0,163, 1, 0, 0, 0, 0, 0, 0,230, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0,230, 0, 0, 0, 18, 0, 0, 0,163, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124,146, 72, 0, 64, 28, 70, - 10,215, 35, 60, 0, 0, 72, 66, 74, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 4, 4, 0,248, 0,164, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 0, 0, 0,191, 1, 0, 0, 31, 1, 0, 0,194, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 0,164, 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, 68, 65, 84, 65, 72, 1, 0, 0, -200,230,208, 3, 0, 0, 0, 0, 38, 1, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -168,194,217, 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, - 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, -248,150,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 16,214, 3, 0, 0, 0, 0, -168, 19,201, 3, 0, 0, 0, 0, 8, 14,201, 3, 0, 0, 0, 0,200, 12,201, 3, 0, 0, 0, 0, 72, 20,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 61, 2, 0, 0,194, 2, 0, 0, 1, 1,216, 0,134, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 75,214, 3, 0, 0, 0, 0,152, 75,214, 3, 0, 0, 0, 0, -200,101,214, 3, 0, 0, 0, 0,120,103,214, 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, 68, 65, 84, 65, 40, 1, 0, 0,200,101,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,120,103,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 68, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,165, 67, 0, 0, 0, 64, 0, 0,208, 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, 73, 1, 0, 0, - 0, 0, 0, 0, 23, 0, 0, 0, 0,128,164, 67, 0, 0,200, 65, 0,128,164, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 74, 1, 24, 0, 74, 1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 61, 2, 0, 0, 61, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,120,103,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,101,214, 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, 25, 4, 0, 0,240, 4, 0, 0, 61, 2, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,216, 0,134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 24,152,214, 3, 0, 0, 0, 0, 68, 65, 84, 65,112, 3, 0, 0, 24,152,214, 3, 0, 0, 0, 0, -173, 0, 0, 0, 1, 0, 0, 0, 56,255, 13, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,228,100, 64, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 65,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0, - 72, 1, 77,190, 0, 0, 0, 0,221,149, 47, 63, 86,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63,225,251,159, 62, -149, 84, 28,191, 0, 0, 0, 0,192, 56, 49,188, 55, 53,101, 63, 52,247,227, 62, 0, 0, 0, 0, 90, 38,173,190, 0,222,192,190, -152, 9, 52,193, 0, 0,128, 63,223,149, 47, 63, 55, 70, 58, 63,160, 56, 49,188, 0, 0, 0, 0, 88,126,162,190,229,251,159, 62, - 55, 53,101, 63, 0, 0, 0, 0, 7,165, 39, 63,150, 84, 28,191, 51,247,227, 62, 0, 0, 0, 0,110,101,239, 64,151, 62,208,192, - 78,255,170, 64, 0, 0,128, 63, 47,201,194, 63, 61, 73,145,191,244,250, 39,191, 8,165, 39,191,190,164,206, 63,209, 10,143, 63, -180,164, 28, 63,149, 84, 28, 63,224,153,196,188,136,239, 76, 64, 10,108,228,190, 52,247,227,190,125, 21, 64,191,126,113,172,191, -216, 49, 49, 65,152, 9, 52, 65,149, 70,158, 62, 24,234,167, 62,192,214,159,187, 0, 0, 6,181,196,188,181,189, 71,238,178, 61, -127, 45,128, 62, 0, 0,226, 51,168,120, 21,194,107, 5, 2, 66,203,135,213,193,147,214,159,192,177, 38, 19, 66,124,173,255,193, - 96,101,210, 65,128, 40,160, 64,221,149, 47, 63, 86,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63,225,251,159, 62, -149, 84, 28,191, 0, 0, 0, 0,192, 56, 49,188, 55, 53,101, 63, 52,247,227, 62, 0, 0, 0, 0, 90, 38,173,190, 0,222,192,190, -152, 9, 52,193, 0, 0,128, 63, 47,201,194, 63, 61, 73,145,191,244,250, 39,191, 8,165, 39,191,190,164,206, 63,209, 10,143, 63, -180,164, 28, 63,149, 84, 28, 63,224,153,196,188,136,239, 76, 64, 10,108,228,190, 52,247,227,190,125, 21, 64,191,126,113,172,191, -216, 49, 49, 65,152, 9, 52, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,103, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,103, 97, 64, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,103, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63,241, 22, 72, 63, 78,162,246,190, 43, 8, 90,190, 2, 35,171,190, 0, 0, 32, 65, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,253,191,136, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 65, 1, 2, 0, 0, -255,255, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0,128, 63,190,133, 65, 66, - 99,212, 90, 66, 27,183,118, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 1, 0, 0, -152, 75,214, 3, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65,205,204, 76, 62, - 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200,213,217, 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, - 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 3, 0, 8, 0,128, 0, 0, 0, 12, 66, 0, 0,128, 63, 10,215, 35, 60, - 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, - 10, 0, 7, 1, 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, 83, 78, 0, 0, 8, 1, 0, 0, 8,156,214, 3, 0, 0, 0, 0, -210, 0, 0, 0, 1, 0, 0, 0,248, 9,215, 3, 0, 0, 0, 0,136, 7,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 67,111,109,112,111,115,105,116,105,110,103, 0,103, 46, 48, 48, 49, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -232, 20,201, 3, 0, 0, 0, 0, 8, 29,201, 3, 0, 0, 0, 0,168,108,171, 3, 0, 0, 0, 0, 24,123,171, 3, 0, 0, 0, 0, -152,157,214, 3, 0, 0, 0, 0, 40,231,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 32, 0, 0, 0,232, 20,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0,136, 21,201, 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, 68, 65, 84, 65, 32, 0, 0, 0,136, 21,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, - 40, 22,201, 3, 0, 0, 0, 0,232, 20,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0, 40, 22,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200, 22,201, 3, 0, 0, 0, 0, -136, 21,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -200, 22,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104, 23,201, 3, 0, 0, 0, 0, 40, 22,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,104, 23,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0, 8, 24,201, 3, 0, 0, 0, 0,200, 22,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8, 24,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -168, 24,201, 3, 0, 0, 0, 0,104, 23,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,234, 3, 1, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0,168, 24,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 25,201, 3, 0, 0, 0, 0, - 8, 24,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6, 92, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, - 72, 25,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232, 25,201, 3, 0, 0, 0, 0,168, 24,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 92, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,232, 25,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0,136, 26,201, 3, 0, 0, 0, 0, 72, 25,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 32, 6,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,136, 26,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, - 40, 27,201, 3, 0, 0, 0, 0,232, 25,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 1, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0, 40, 27,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200, 27,201, 3, 0, 0, 0, 0, -136, 26,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -200, 27,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104, 28,201, 3, 0, 0, 0, 0, 40, 27,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4, 3,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,104, 28,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0, 8, 29,201, 3, 0, 0, 0, 0,200, 27,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 3, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8, 29,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,104, 28,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,168,108,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88,109,171, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,136, 21,201, 3, 0, 0, 0, 0, 40, 22,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0, 88,109,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8,110,171, 3, 0, 0, 0, 0, -168,108,171, 3, 0, 0, 0, 0,136, 21,201, 3, 0, 0, 0, 0,104, 23,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0, 8,110,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184,110,171, 3, 0, 0, 0, 0, - 88,109,171, 3, 0, 0, 0, 0, 40, 22,201, 3, 0, 0, 0, 0, 8, 24,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,184,110,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104,111,171, 3, 0, 0, 0, 0, - 8,110,171, 3, 0, 0, 0, 0,104, 23,201, 3, 0, 0, 0, 0, 8, 24,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,104,111,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24,112,171, 3, 0, 0, 0, 0, -184,110,171, 3, 0, 0, 0, 0,200, 22,201, 3, 0, 0, 0, 0, 72, 25,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0, 24,112,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200,112,171, 3, 0, 0, 0, 0, -104,111,171, 3, 0, 0, 0, 0,168, 24,201, 3, 0, 0, 0, 0, 72, 25,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,200,112,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120,113,171, 3, 0, 0, 0, 0, - 24,112,171, 3, 0, 0, 0, 0, 8, 24,201, 3, 0, 0, 0, 0,232, 25,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,120,113,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40,114,171, 3, 0, 0, 0, 0, -200,112,171, 3, 0, 0, 0, 0,104, 23,201, 3, 0, 0, 0, 0,232, 25,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0, 40,114,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216,114,171, 3, 0, 0, 0, 0, -120,113,171, 3, 0, 0, 0, 0,168, 24,201, 3, 0, 0, 0, 0,232, 25,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,216,114,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136,115,171, 3, 0, 0, 0, 0, - 40,114,171, 3, 0, 0, 0, 0, 8, 24,201, 3, 0, 0, 0, 0, 72, 25,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,136,115,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56,116,171, 3, 0, 0, 0, 0, -216,114,171, 3, 0, 0, 0, 0,104, 23,201, 3, 0, 0, 0, 0,136, 26,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0, 56,116,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232,116,171, 3, 0, 0, 0, 0, -136,115,171, 3, 0, 0, 0, 0,232, 25,201, 3, 0, 0, 0, 0, 40, 27,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,232,116,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152,117,171, 3, 0, 0, 0, 0, - 56,116,171, 3, 0, 0, 0, 0,136, 26,201, 3, 0, 0, 0, 0, 40, 27,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,152,117,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72,118,171, 3, 0, 0, 0, 0, -232,116,171, 3, 0, 0, 0, 0,136, 26,201, 3, 0, 0, 0, 0,200, 27,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0, 72,118,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248,118,171, 3, 0, 0, 0, 0, -152,117,171, 3, 0, 0, 0, 0, 40, 27,201, 3, 0, 0, 0, 0,200, 27,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,248,118,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168,119,171, 3, 0, 0, 0, 0, - 72,118,171, 3, 0, 0, 0, 0,232, 20,201, 3, 0, 0, 0, 0,104, 28,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,168,119,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88,120,171, 3, 0, 0, 0, 0, -248,118,171, 3, 0, 0, 0, 0,104, 28,201, 3, 0, 0, 0, 0, 8, 29,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0, 88,120,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8,121,171, 3, 0, 0, 0, 0, -168,119,171, 3, 0, 0, 0, 0,200, 22,201, 3, 0, 0, 0, 0, 8, 29,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0, 8,121,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184,121,171, 3, 0, 0, 0, 0, - 88,120,171, 3, 0, 0, 0, 0,168, 24,201, 3, 0, 0, 0, 0, 8, 29,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,184,121,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104,122,171, 3, 0, 0, 0, 0, - 8,121,171, 3, 0, 0, 0, 0,200, 27,201, 3, 0, 0, 0, 0,104, 28,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0,104,122,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24,123,171, 3, 0, 0, 0, 0, -184,121,171, 3, 0, 0, 0, 0, 40, 27,201, 3, 0, 0, 0, 0, 8, 29,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 0, 0, 0, 24,123,171, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -104,122,171, 3, 0, 0, 0, 0,232, 20,201, 3, 0, 0, 0, 0,136, 26,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,160, 0, 0, 0,152,157,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,184,158,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,104, 23,201, 3, 0, 0, 0, 0,136, 21,201, 3, 0, 0, 0, 0, 40, 22,201, 3, 0, 0, 0, 0, - 8, 24,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,235, 3, 0, 0, 5, 4, 0, 0, - 7, 7,127, 7, 27, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,198,207, 3, 0, 0, 0, 0, - 88,198,207, 3, 0, 0, 0, 0, 40,105,214, 3, 0, 0, 0, 0,216,106,214, 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, 68, 65, 84, 65, 40, 1, 0, 0, - 40,105,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216,106,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 32,148, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,235, 3, 0, 0, 4, 4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, -216,106,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,105,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0,240,109, 69, 0, 0,128,192, 0, 0, 0, 0, 0, 0, 0, 0,255,255,109, 69, 0, 0, 0,192, 0, 0, 0, 0, -112, 7, 0, 0,129, 7, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0,111, 7, 0, 0, 18, 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,128, 63, 0, 0,128, 63, 2, 0, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,129, 7, 2, 0,112, 7, 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, 5, 4, 0, 0, 5, 4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65,160, 0, 0, 0, -184,158,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,216,159,214, 3, 0, 0, 0, 0,152,157,214, 3, 0, 0, 0, 0, - 8, 29,201, 3, 0, 0, 0, 0,168, 24,201, 3, 0, 0, 0, 0, 72, 25,201, 3, 0, 0, 0, 0,200, 22,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 91, 0, 0, 0, 15, 15, 94, 1, 92, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 94,200, 3, 0, 0, 0, 0, 40, 94,200, 3, 0, 0, 0, 0, -136,108,214, 3, 0, 0, 0, 0, 56,110,214, 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, 68, 65, 84, 65, 40, 1, 0, 0,136,108,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 56,110,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,115, 68, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,175, 67, 0, 0, 0, 0, 0, 0,208, 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, 93, 1, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0,128,174, 67, 0, 0,200, 65, 0,128,174, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 94, 1, 26, 0, 94, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56,110,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,108,214, 3, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, - 0, 0, 0, 0, 0, 0, 72, 66, 50, 51, 74,193,154,209,131, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 93, 1, 0, 0, - 18, 0, 0, 0, 65, 0, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, - 72, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 4, 8, 0, 94, 1, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 26, 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 1, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,208, 0, 0, 0, 40, 94,200, 3, 0, 0, 0, 0, -190, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, -216,159,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,248,224,214, 3, 0, 0, 0, 0,184,158,214, 3, 0, 0, 0, 0, -168, 24,201, 3, 0, 0, 0, 0,232, 25,201, 3, 0, 0, 0, 0, 8, 24,201, 3, 0, 0, 0, 0, 72, 25,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 93, 0, 0, 0,233, 3, 0, 0, 4, 4, 94, 1,141, 3, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,125,199, 3, 0, 0, 0, 0, 56,125,199, 3, 0, 0, 0, 0, -232,111,214, 3, 0, 0, 0, 0, 40,161,214, 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, 68, 65, 84, 65, 40, 1, 0, 0,232,111,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 40,161,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148, 67, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,175, 67, 0, 0, 0, 0, 0, 0,208, 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, 93, 1, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0,128,174, 67, 0, 0,200, 65, 0,128,174, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 94, 1, 26, 0, 94, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0,208, 3, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 40,161,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,111,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,174, 67, - 0,128, 92,196, 0, 0, 0, 0, 0, 0, 0, 0,255,127,166, 67,255,191, 92,196, 0, 0, 0, 0, 77, 1, 0, 0, 94, 1, 0, 0, - 0, 0, 0, 0,114, 3, 0, 0, 0, 0, 0, 0, 82, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 76, 1, 0, 0, - 0, 0, 0, 0,114, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, - 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0, 94, 1,115, 3, 77, 1,115, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 93, 0, 0, 0,207, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 1,115, 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, -120, 77,214, 3, 0, 0, 0, 0, 8,210,214, 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, 68, 65, 84, 65, 88, 1, 0, 0,120, 77,214, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 88, 79,214, 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, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, 67,111,110,116,101,120,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,220,255, 76, 1, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0, 88, 79,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 40,193,214, 3, 0, 0, 0, 0, -120, 77,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255, 76, 1, 61, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 40,193,214, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 8,195,214, 3, 0, 0, 0, 0, 88, 79,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,255, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0, 8,195,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,232,196,214, 3, 0, 0, 0, 0, - 40,193,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101,110,115,105,111, -110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140,254, 76, 1,203, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,232,196,214, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,200,198,214, 3, 0, 0, 0, 0, 8,195,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 65,110,116,105, 45, 65,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58,254, 76, 1, 58, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0,200,198,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,168,200,214, 3, 0, 0, 0, 0, -232,196,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97,109,112,108,101,100, 32, - 77,111,116,105,111,110, 32, 66,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,254, 76, 1, 0, 0, - 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,168,200,214, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,136,202,214, 3, 0, 0, 0, 0,200,198,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,254, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0,136,202,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,104,204,214, 3, 0, 0, 0, 0, -168,200,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,101,114,102,111,114,109, 97, -110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,242,253, 76, 1, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,104,204,214, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 72,206,214, 3, 0, 0, 0, 0,136,202,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110, -103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110, -103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 80,111,115,116, 32, 80,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,218,253, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0, 72,206,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 40,208,214, 3, 0, 0, 0, 0, -104,204,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194,253, 76, 1, 0, 0, - 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 40,208,214, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 8,210,214, 3, 0, 0, 0, 0, 72,206,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, 79,117,116,112,117,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, 40,253, 76, 1,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0, 8,210,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 40,208,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,253, 76, 1, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, 56,125,199, 3, 0, 0, 0, 0, -179, 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, 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, 2, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,255, 21, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,160, 0, 0, 0,248,224,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 8,230,214, 3, 0, 0, 0, 0, -216,159,214, 3, 0, 0, 0, 0,104, 28,201, 3, 0, 0, 0, 0,200, 27,201, 3, 0, 0, 0, 0, 40, 27,201, 3, 0, 0, 0, 0, - 8, 29,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, 0, 31, 6, 0, 0, 0, 0, 0, 0,139, 1, 0, 0, - 1, 1, 27, 3,140, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,211,214, 3, 0, 0, 0, 0, -232,211,214, 3, 0, 0, 0, 0,216,162,214, 3, 0, 0, 0, 0,152,169,214, 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, 68, 65, 84, 65, 40, 1, 0, 0, -216,162,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,136,164,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 64,113, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,192, 70, 68, 0, 0, 0, 0, 0, 0,208, 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, 26, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128, 70, 68, 0, 0,200, 65, 0,128, 70, 68, 0, 0,200, 65, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 27, 3, 26, 0, 27, 3, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, 0, 31, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 3, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, -136,164,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 56,166,214, 3, 0, 0, 0, 0,216,162,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 15, 67, 0, 64, 70,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67,255,127, 70,196, 0, 0, 0, 0, -143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0, 44, 3,143, 0, 26, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, 0, 5, 3, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,114, 1, 0, 0, 5, 0, 3, 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, 68, 65, 84, 65, 40, 1, 0, 0, - 56,166,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,232,167,214, 3, 0, 0, 0, 0,136,164,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 16, 67, 0, 0,206,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, 0, 0,206,194, 0, 0, 0, 0, -143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0,102, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, 0, 31, 6, 0, 0, 26, 0, 0, 0, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 6, 0, 34, 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, 68, 65, 84, 65, 40, 1, 0, 0, -232,167,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,152,169,214, 3, 0, 0, 0, 0, 56,166,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 35, 67, 0,192,108,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0, 0,184,195, 0, 0, 0, 0, -163, 0, 0, 0,180, 0, 0, 0, 18, 0, 0, 0,129, 1, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0,162, 0, 0, 0, 18, 0, 0, 0,129, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,180, 0,130, 1,163, 0,112, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 6, 0, 0, 31, 6, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0, -152,169,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,167,214, 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, 5, 3, 0, 0, 31, 6, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 3,114, 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, 24,226,214, 3, 0, 0, 0, 0, 68, 65, 84, 65,112, 3, 0, 0, - 24,226,214, 3, 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0, 93,101,230, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 30,133,119, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 65,128,191, 0, 0,128,191, - 0, 0, 0, 0, 0, 0, 0, 0, 72, 1, 77,190, 0, 0, 0, 0,221,149, 47, 63, 85,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, - 51, 70, 58, 63,225,251,159, 62,149, 84, 28,191, 0, 0, 0, 0,191, 56, 49,188, 54, 53,101, 63, 50,247,227, 62, 0, 0, 0, 0, - 90, 38,173,190,254,221,192,190,152, 9, 52,193, 0, 0,128, 63,223,149, 47, 63, 55, 70, 58, 63,192, 56, 49,188, 0, 0, 0, 0, - 87,126,162,190,228,251,159, 62, 56, 53,101, 63, 0, 0, 0, 0, 7,165, 39, 63,150, 84, 28,191, 50,247,227, 62, 0, 0, 0, 0, -110,101,239, 64,151, 62,208,192, 77,255,170, 64, 0, 0,128, 63, 42, 6,158, 63, 99, 28,157,191,244,250, 39,191, 8,165, 39,191, -211,164,167, 63, 55,175,154, 63,180,164, 28, 63,149, 84, 28, 63, 39,127,159,188,135,157, 93, 64, 8,108,228,190, 50,247,227,190, - 4,213, 27,191,122,122,186,191,216, 49, 49, 65,152, 9, 52, 65, 25, 25,195, 62,176,249,206, 62,128,238,196,187, 0, 0,192,179, - 55, 15,168,189,201,118,165, 61,152, 15,109, 62, 0, 0,152, 51,211,120, 21,194,144, 5, 2, 66, 6,136,213,193,193,214,159,192, -219, 38, 19, 66,196,173,255,193,154,101,210, 65,173, 40,160, 64,221,149, 47, 63, 85,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, - 51, 70, 58, 63,225,251,159, 62,149, 84, 28,191, 0, 0, 0, 0,191, 56, 49,188, 54, 53,101, 63, 50,247,227, 62, 0, 0, 0, 0, - 90, 38,173,190,254,221,192,190,152, 9, 52,193, 0, 0,128, 63, 42, 6,158, 63, 99, 28,157,191,244,250, 39,191, 8,165, 39,191, -211,164,167, 63, 55,175,154, 63,180,164, 28, 63,149, 84, 28, 63, 39,127,159,188,135,157, 93, 64, 8,108,228,190, 50,247,227,190, - 4,213, 27,191,122,122,186,191,216, 49, 49, 65,152, 9, 52, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,250,150, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 62,250,150, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,250,150, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,241, 22, 72, 63, 78,162,246,190, 44, 8, 90,190, 3, 35,171,190, -214,211,111, 65,214,211,111, 65, 0, 0, 0, 0, 0, 0, 0, 0, 80, 49,183, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,160, 65, 1, 2, 0, 0,255,255, 0, 0, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, 3,236,234,190, 1, 0, 0, 0, - 0, 0,128, 63,190,133, 65, 66,100,212, 90, 66, 31,183,118, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 96, 1, 0, 0,232,211,214, 3, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, 51, 51, 51, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32, 65,205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200,213,217, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, 8, 8,128, 0, 0, 0, 12, 66, - 0, 0,128, 63,205,204,204, 61, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 16, 0, 10, 0, 7, 1, 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, 68, 65, 84, 65,160, 0, 0, 0, - 8,230,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 40,231,214, 3, 0, 0, 0, 0,248,224,214, 3, 0, 0, 0, 0, -136, 26,201, 3, 0, 0, 0, 0,104, 23,201, 3, 0, 0, 0, 0,232, 25,201, 3, 0, 0, 0, 0, 40, 27,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 6, 0, 0,141, 1, 0, 0,233, 3, 0, 0, 16, 16, 32, 6, 93, 2, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,174,214, 3, 0, 0, 0, 0,168,174,214, 3, 0, 0, 0, 0, - 72,171,214, 3, 0, 0, 0, 0,248,172,214, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72,171,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,248,172,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 66, 68, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,196, 68, 0, 0, 0, 0, 0, 0,208, 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, 31, 6, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0,224,195, 68, 0, 0,200, 65, 0,224,195, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 32, 6, 26, 0, 32, 6, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 6, 0, 0,141, 1, 0, 0,166, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 6, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,248,172,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,171,214, 3, 0, 0, 0, 0, 0, 0, 32,193, 0, 0, 0, 68, - 0, 0, 32,193, 0, 0, 0, 68,128,195,217,195,192,225,108, 68, 96,240,187, 64, 62, 16,253, 67, 15, 6, 0, 0, 32, 6, 0, 0, - 18, 0, 0, 0, 66, 2, 0, 0, 0, 0, 0, 0, 14, 6, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 14, 6, 0, 0, - 18, 0, 0, 0, 66, 2, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,250, 70, 0, 0,250, 70,236, 81,184, 61, 10,215, 19, 64, - 10, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 32, 6, 67, 2, 15, 6, 49, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 6, 0, 0,167, 1, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 6, 67, 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, 68, 65, 84, 65, 48, 1, 0, 0,168,174,214, 3, 0, 0, 0, 0, -191, 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, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 10,215, 19, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 10,206, 97, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, - 40,231,214, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,230,214, 3, 0, 0, 0, 0, -232, 20,201, 3, 0, 0, 0, 0,136, 26,201, 3, 0, 0, 0, 0,200, 27,201, 3, 0, 0, 0, 0,104, 28,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0,139, 1, 0, 0, 6, 6, 4, 3,140, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,232,214, 3, 0, 0, 0, 0, 72,232,214, 3, 0, 0, 0, 0, - 88,176,214, 3, 0, 0, 0, 0,184,179,214, 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, 68, 65, 84, 65, 40, 1, 0, 0, 88,176,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 8,178,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,215, 67, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 65, 68, 0, 0, 0, 0, 0, 0,208, 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, 3, 3, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0,192, 64, 68, 0, 0,200, 65, 0,192, 64, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 4, 3, 26, 0, 4, 3, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8,178,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,184,179,214, 3, 0, 0, 0, 0, 88,176,214, 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, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 0, 3, 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, 68, 65, 84, 65, 40, 1, 0, 0,184,179,214, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,178,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 67, 0, 0,129,191, 0,128, 0, 64, 0, 0,100,190, 0,128,156, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 0, 0, - 0, 0, 0, 0,114, 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, 3, 3, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4, 3,114, 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, 68, 65, 84, 65, 40, 33, 0, 0, 72,232,214, 3, 0, 0, 0, 0, -184, 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, 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,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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,240, 65, 0, 0, 0, 0,154,153,153, 62, - 0, 0, 0, 0,100, 0, 0, 0,154,153,153, 62,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 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, 0,100, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 83, 78, 0, 0, 8, 1, 0, 0,248, 9,215, 3, 0, 0, 0, 0, -210, 0, 0, 0, 1, 0, 0, 0,152, 66,216, 3, 0, 0, 0, 0, 8,156,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 68,101,102, 97,117,108,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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -168, 29,201, 3, 0, 0, 0, 0,136, 36,201, 3, 0, 0, 0, 0,200,123,171, 3, 0, 0, 0, 0,120,135,171, 3, 0, 0, 0, 0, -184, 11,215, 3, 0, 0, 0, 0, 56, 16,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,102, 10, 64, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,168, 29,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0, 72, 30,201, 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, 68, 65, 84, 65, 32, 0, 0, 0, 72, 30,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -232, 30,201, 3, 0, 0, 0, 0,168, 29,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,178, 2, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0,232, 30,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136, 31,201, 3, 0, 0, 0, 0, - 72, 30,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 5,178, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -136, 31,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40, 32,201, 3, 0, 0, 0, 0,232, 30,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 70, 5, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 40, 32,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0,200, 32,201, 3, 0, 0, 0, 0,136, 31,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,151, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,200, 32,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -104, 33,201, 3, 0, 0, 0, 0, 40, 32,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 5,151, 2, 1, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0,104, 33,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8, 34,201, 3, 0, 0, 0, 0, -200, 32,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112, 4, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, - 8, 34,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,168, 34,201, 3, 0, 0, 0, 0,104, 33,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,112, 4,151, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,168, 34,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0, 72, 35,201, 3, 0, 0, 0, 0, 8, 34,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -112, 4, 56, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 72, 35,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -232, 35,201, 3, 0, 0, 0, 0,168, 34,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 5, 56, 2, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0,232, 35,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136, 36,201, 3, 0, 0, 0, 0, - 72, 35,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -136, 36,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232, 35,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,112, 4, 84, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,123,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,120,124,171, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 30,201, 3, 0, 0, 0, 0, -232, 30,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120,124,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 40,125,171, 3, 0, 0, 0, 0,200,123,171, 3, 0, 0, 0, 0, 72, 30,201, 3, 0, 0, 0, 0, - 40, 32,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,125,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,216,125,171, 3, 0, 0, 0, 0,120,124,171, 3, 0, 0, 0, 0,232, 30,201, 3, 0, 0, 0, 0, -200, 32,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,125,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,136,126,171, 3, 0, 0, 0, 0, 40,125,171, 3, 0, 0, 0, 0, 40, 32,201, 3, 0, 0, 0, 0, -200, 32,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136,126,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 56,127,171, 3, 0, 0, 0, 0,216,125,171, 3, 0, 0, 0, 0,168, 29,201, 3, 0, 0, 0, 0, -104, 33,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,127,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,232,127,171, 3, 0, 0, 0, 0,136,126,171, 3, 0, 0, 0, 0,136, 31,201, 3, 0, 0, 0, 0, -104, 33,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232,127,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,152,128,171, 3, 0, 0, 0, 0, 56,127,171, 3, 0, 0, 0, 0, 40, 32,201, 3, 0, 0, 0, 0, - 8, 34,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,152,128,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 72,129,171, 3, 0, 0, 0, 0,232,127,171, 3, 0, 0, 0, 0,200, 32,201, 3, 0, 0, 0, 0, - 8, 34,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72,129,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,248,129,171, 3, 0, 0, 0, 0,152,128,171, 3, 0, 0, 0, 0,104, 33,201, 3, 0, 0, 0, 0, -168, 34,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248,129,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,168,130,171, 3, 0, 0, 0, 0, 72,129,171, 3, 0, 0, 0, 0, 8, 34,201, 3, 0, 0, 0, 0, -168, 34,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168,130,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 88,131,171, 3, 0, 0, 0, 0,248,129,171, 3, 0, 0, 0, 0,200, 32,201, 3, 0, 0, 0, 0, - 72, 35,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88,131,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 8,132,171, 3, 0, 0, 0, 0,168,130,171, 3, 0, 0, 0, 0,136, 31,201, 3, 0, 0, 0, 0, - 72, 35,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8,132,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,184,132,171, 3, 0, 0, 0, 0, 88,131,171, 3, 0, 0, 0, 0,168, 34,201, 3, 0, 0, 0, 0, - 72, 35,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184,132,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,104,133,171, 3, 0, 0, 0, 0, 8,132,171, 3, 0, 0, 0, 0,168, 29,201, 3, 0, 0, 0, 0, -232, 35,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104,133,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 24,134,171, 3, 0, 0, 0, 0,184,132,171, 3, 0, 0, 0, 0, 40, 32,201, 3, 0, 0, 0, 0, -232, 35,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24,134,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,200,134,171, 3, 0, 0, 0, 0,104,133,171, 3, 0, 0, 0, 0, 8, 34,201, 3, 0, 0, 0, 0, -136, 36,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,134,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,120,135,171, 3, 0, 0, 0, 0, 24,134,171, 3, 0, 0, 0, 0,104, 33,201, 3, 0, 0, 0, 0, -136, 36,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120,135,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,134,171, 3, 0, 0, 0, 0,232, 35,201, 3, 0, 0, 0, 0, -136, 36,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,184, 11,215, 3, 0, 0, 0, 0, -214, 0, 0, 0, 1, 0, 0, 0,216, 12,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 32,201, 3, 0, 0, 0, 0, - 72, 30,201, 3, 0, 0, 0, 0,232, 30,201, 3, 0, 0, 0, 0,200, 32,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 70, 5, 0, 0,152, 2, 0, 0,178, 2, 0, 0, 7, 7, 71, 5, 27, 0, 1, 0, 0, 0, 0, 0, 7, 0, 8, 0, - 72,207,177, 3, 0, 0, 0, 0, 24,199,207, 3, 0, 0, 0, 0, 24,199,207, 3, 0, 0, 0, 0,104,181,214, 3, 0, 0, 0, 0, - 24,183,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,196,207, 3, 0, 0, 0, 0, -216,196,207, 3, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,104,181,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, - 24,183,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,163, 68, 0, 0, 0, 0, 0, 0,208, 65, - 0, 0, 0, 0, 0,224,168, 68, 0, 0, 0, 0, 0, 0,208, 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, 70, 5, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, - 0,192,168, 68, 0, 0,200, 65, 0,192,168, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, - 4, 0, 12, 0, 10, 0, 71, 5, 26, 0, 71, 5, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 70, 5, 0, 0,152, 2, 0, 0,177, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 71, 5, 26, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 88, 6,178, 3, 0, 0, 0, 0,120,128,214, 15, 0, 0, 0, 0,120,128,214, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,120, 13,163, 3, 0, 0, 0, 0,216, 19,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 24,183,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,104,181,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,109, 69, 0, 0,128,192, 0, 0, 0, 0, - 0, 0, 0, 0, 0,192,168, 68, 0, 0, 0, 0, 0, 0, 0, 64, 70, 5, 0, 0, 87, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 69, 5, 0, 0, 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,128, 63, 0, 0,128, 63, 2, 0, 0, 0, 1, 0, 3, 3, - 2, 0, 0, 4, 10, 0, 87, 5, 2, 0, 70, 5, 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,178, 2, 0, 0,178, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 40, 5,178, 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,232, 20,163, 3, 0, 0, 0, 0,248,116,208, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,216, 12,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, -248, 13,215, 3, 0, 0, 0, 0,184, 11,215, 3, 0, 0, 0, 0,104, 33,201, 3, 0, 0, 0, 0,168, 34,201, 3, 0, 0, 0, 0, - 72, 35,201, 3, 0, 0, 0, 0,136, 31,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,113, 4, 0, 0, 70, 5, 0, 0, - 0, 0, 0, 0, 55, 2, 0, 0, 4, 4,214, 0, 56, 2, 1, 0, 0, 0, 0, 0, 0, 0, 8, 0,248,205,177, 3, 0, 0, 0, 0, -184,126,199, 3, 0, 0, 0, 0,184,126,199, 3, 0, 0, 0, 0,200,184,214, 3, 0, 0, 0, 0,120,186,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,205,207, 3, 0, 0, 0, 0, 88,195,207, 3, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 1, 0, 0,200,184,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,120,186,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 86, 67, - 0, 0, 0, 0, 0, 0,208, 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,213, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 85, 67, 0, 0,200, 65, - 0, 0, 85, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,214, 0, - 26, 0,214, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,113, 4, 0, 0, 70, 5, 0, 0, - 30, 2, 0, 0, 55, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,214, 0, 26, 0, 4, 0, 1, 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,248, 3,178, 3, 0, 0, 0, 0, -200, 53,163, 3, 0, 0, 0, 0,200, 53,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8,118,208, 3, 0, 0, 0, 0, 56,121,208, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 1, 0, 0,120,186,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -200,184,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0, 0, 61,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 67, - 0,128, 7,196, 0, 0, 0, 0,197, 0, 0, 0,214, 0, 0, 0, 0, 0, 0, 0, 29, 2, 0, 0, 0, 0, 0, 0, 74, 1, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,196, 0, 0, 0, 0, 0, 0, 0, 29, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,214, 0, - 30, 2,197, 0, 30, 2, 0, 0, 72, 91,192, 15, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,113, 4, 0, 0, 70, 5, 0, 0, - 0, 0, 0, 0, 29, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,214, 0, 30, 2, 5, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 2,178, 3, 0, 0, 0, 0, - 8,150,212, 15, 0, 0, 0, 0,152, 72,163, 3, 0, 0, 0, 0,200,213,214, 3, 0, 0, 0, 0,184, 75,215, 3, 0, 0, 0, 0, - 72,122,208, 3, 0, 0, 0, 0,152,127,208, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0,200,213,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,168,215,214, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,232, 35,178, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 85, 84, 84, 79, 78, 83, 95, - 80, 84, 95, 99,111,110,116,101,120,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, 66, 85, 84, 84, 79, 78, 83, 95, - 80, 84, 95, 99,111,110,116,101,120,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, 67,111,110,116,101,120,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,220,255,197, 0, 36, 0, - 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,168,215,214, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,136,217,214, 3, 0, 0, 0, 0,200,213,214, 3, 0, 0, 0, 0, 40, 34,221, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255,197, 0, 61, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 11, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0,136,217,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,104,219,214, 3, 0, 0, 0, 0, -168,215,214, 3, 0, 0, 0, 0,200, 35,221, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,121,101,114,115, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 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,255,197, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,104,219,214, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 72,221,214, 3, 0, 0, 0, 0,136,217,214, 3, 0, 0, 0, 0,104, 37,221, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140,254,197, 0,203, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 13, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0, 72,221,214, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,184, 43,215, 3, 0, 0, 0, 0, -104,219,214, 3, 0, 0, 0, 0, 8, 39,221, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,110,116,105, 45, 65,108,105, - 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58,254,197, 0, 58, 0, - 20, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,184, 43,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,152, 45,215, 3, 0, 0, 0, 0, 72,221,214, 3, 0, 0, 0, 0,168, 40,221, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 97,109,112,108,101,100, 32, 77,111,116,105,111,110, 32, 66,108,117,114, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,254,197, 0, 0, 0, 20, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0,152, 45,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,120, 47,215, 3, 0, 0, 0, 0, -184, 43,215, 3, 0, 0, 0, 0, 72, 42,221, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,104, 97,100,105,110,103, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,254,197, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,120, 47,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 88, 49,215, 3, 0, 0, 0, 0,152, 45,215, 3, 0, 0, 0, 0,232, 43,221, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,242,253,197, 0, 0, 0, 0, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0, 88, 49,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 56, 51,215, 3, 0, 0, 0, 0, -120, 47,215, 3, 0, 0, 0, 0,136, 45,221, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,111,115,116, 32, 80,114,111, - 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,218,253,197, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 56, 51,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 24, 53,215, 3, 0, 0, 0, 0, 88, 49,215, 3, 0, 0, 0, 0, 72, 48,221, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194,253,197, 0, 0, 0, 20, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 19, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0, 24, 53,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,248, 54,215, 3, 0, 0, 0, 0, - 56, 51,215, 3, 0, 0, 0, 0,232, 49,221, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,111,117,116,112,117,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, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,111,117,116,112,117,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, 79,117,116,112,117,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, 36,253,197, 0,134, 0, - 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,248, 54,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,216, 56,215, 3, 0, 0, 0, 0, 24, 53,215, 3, 0, 0, 0, 0, 40, 53,221, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,253,197, 0, 0, 0, 0, 0, 0, 0, 4, 0, 7, 0, 0, 0, 0, 0, 21, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0,216, 56,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,184, 58,215, 3, 0, 0, 0, 0, -248, 54,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, - 95,115, 99,101,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, - 95,115, 99,101,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 99,101,110,101, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255, 41, 1, 61, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,184, 58,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,152, 60,215, 3, 0, 0, 0, 0,216, 56,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,117,110,105,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, 83, 67, 69, 78, 69, 95, 80, 84, 95,117,110,105,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, 85,110,105,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28,255, 41, 1, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0,152, 60,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,120, 62,215, 3, 0, 0, 0, 0, -184, 58,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, - 95,107,101,121,105,110,103, 95,115,101,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, - 95,107,101,121,105,110,103, 95,115,101,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75,101,121,105,110,103, 32, 83, -101,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191,254, 41, 1, 69, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,120, 62,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 88, 64,215, 3, 0, 0, 0, 0,152, 60,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 71,114, 97,118,105,116,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,131,254, 41, 1, 36, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0, 88, 64,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 56, 66,215, 3, 0, 0, 0, 0, -120, 62,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, - 95,115,105,109,112,108,105,102,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, - 95,115,105,109,112,108,105,102,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,105,109,112,108,105,102,121, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27,254, 41, 1, 80, 0, - 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 56, 66,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 24, 68,215, 3, 0, 0, 0, 0, 88, 64,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95, 99,117,115,116,111,109, 95,112,114,111,112,115, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95, 99,117,115,116,111,109, 95,112,114,111,112,115, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 67,117,115,116,111,109, 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,223,253, 41, 1, 36, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0, 24, 68,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,248, 69,215, 3, 0, 0, 0, 0, - 56, 66,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, - 80, 84, 95, 99,111,110,116,101,120,116, 95,116,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, - 80, 84, 95, 99,111,110,116,101,120,116, 95,116,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,255,187, 0,204, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 5, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,248, 69,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,216, 71,215, 3, 0, 0, 0, 0, 24, 68,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, 80, 84, 95,109, 97,112,112,105,110,103, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, 80, 84, 95,109, 97,112,112,105,110,103, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,112,112,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77,254,187, 0,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0,216, 71,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,184, 75,215, 3, 0, 0, 0, 0, -248, 69,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, - 80, 84, 95,105,110,102,108,117,101,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, - 80, 84, 95,105,110,102,108,117,101,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73,110,102,108,117,101,110, 99, -101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,223,252,187, 0, 86, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,184, 75,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 71,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 74, 69, 67, 84, 95, 80, 84, 95, 99,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 74, 69, 67, 84, 95, 80, 84, 95, 99,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 79, 98,106,101, 99,116, 32, 67,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160,255,187, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65,248, 0, 0, 0,184,126,199, 3, 0, 0, 0, 0,179, 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, 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, 2, 0, 1, 0, 0, 0, 0, 0,232,198,226, 3, 0, 0, 0, 0,255, 21, 0, 0,160, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,248, 13,215, 3, 0, 0, 0, 0, -214, 0, 0, 0, 1, 0, 0, 0, 24, 15,215, 3, 0, 0, 0, 0,216, 12,215, 3, 0, 0, 0, 0,168, 29,201, 3, 0, 0, 0, 0, -232, 35,201, 3, 0, 0, 0, 0,136, 36,201, 3, 0, 0, 0, 0,104, 33,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,111, 4, 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, 15, 15,112, 4, 84, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -152,104,177, 3, 0, 0, 0, 0,120, 95,200, 3, 0, 0, 0, 0,120, 95,200, 3, 0, 0, 0, 0, 40,188,214, 3, 0, 0, 0, 0, -216,189,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,207,207, 3, 0, 0, 0, 0, -216,205,207, 3, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 40,188,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, -216,189,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,146, 68, 0, 0, 0, 0, 0, 0,208, 65, - 0, 0, 0, 0, 0, 0,142, 68, 0, 0, 0, 0, 0, 0,208, 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,111, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, - 0,224,141, 68, 0, 0,200, 65, 0,224,141, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, - 4, 0, 12, 0, 10, 0,112, 4, 26, 0,112, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,111, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -112, 4, 26, 0, 6, 0, 1, 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, -232,186,177, 3, 0, 0, 0, 0,232,169,209, 15, 0, 0, 0, 0,232,169,209, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,168,128,208, 3, 0, 0, 0, 0,216,131,208, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,216,189,214, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 40,188,214, 3, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 72, 66, - 88,218,103,194, 40,147,141, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,111, 4, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,111, 4, 0, 0, 18, 0, 0, 0, 57, 0, 0, 0, - 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, 72, 0, 0, 0, 0, 0, 0, 2, - 4, 0, 0, 4, 8, 0,112, 4, 58, 0, 0, 0, 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, 4, 0, 0, 26, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -112, 4, 58, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184,185,177, 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,232,132,208, 3, 0, 0, 0, 0, 88,140,208, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,208, 0, 0, 0,120, 95,200, 3, 0, 0, 0, 0,190, 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, - 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 24, 15,215, 3, 0, 0, 0, 0, -214, 0, 0, 0, 1, 0, 0, 0, 56, 16,215, 3, 0, 0, 0, 0,248, 13,215, 3, 0, 0, 0, 0,168, 34,201, 3, 0, 0, 0, 0, - 8, 34,201, 3, 0, 0, 0, 0,200, 32,201, 3, 0, 0, 0, 0, 72, 35,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -113, 4, 0, 0, 70, 5, 0, 0, 57, 2, 0, 0,150, 2, 0, 0, 3, 3,214, 0, 94, 0, 1, 0, 0, 0, 0, 0, 0, 0, 8, 0, - 72,103,177, 3, 0, 0, 0, 0,200, 0,209, 3, 0, 0, 0, 0,200, 0,209, 3, 0, 0, 0, 0,184,107,215, 3, 0, 0, 0, 0, -104,109,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,209,207, 3, 0, 0, 0, 0, - 24,208,207, 3, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,184,107,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, -104,109,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,244, 67, 0, 0, 0, 0, 0, 0,208, 65, - 0, 0, 0, 0, 0, 0, 86, 67, 0, 0, 0, 0, 0, 0,208, 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,213, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, - 0, 0, 85, 67, 0, 0,200, 65, 0, 0, 85, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, - 4, 0, 12, 0, 10, 0,214, 0, 26, 0,214, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -113, 4, 0, 0, 70, 5, 0, 0,125, 2, 0, 0,150, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -214, 0, 26, 0, 8, 0, 1, 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, -136,184,177, 3, 0, 0, 0, 0, 40, 59,163, 3, 0, 0, 0, 0, 40, 59,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,104,141,208, 3, 0, 0, 0, 0,152,144,208, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,104,109,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,184,107,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,141, 67, 0, 0,244,194, 0, 0, 0, 0, - 0, 0, 0, 64, 0, 0, 71, 67, 0, 0,143,194, 0, 0,172,193,197, 0, 0, 0,214, 0, 0, 0, 18, 0, 0, 0, 67, 0, 0, 0, - 0, 0, 0, 0,196, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,196, 0, 0, 0, 18, 0, 0, 0, 67, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 18, 0, 0, 0, 2, 0, 3, 3, - 0, 0, 12, 4, 6, 0,214, 0, 68, 0,197, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -113, 4, 0, 0, 70, 5, 0, 0, 57, 2, 0, 0,124, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -214, 0, 68, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 88,183,177, 3, 0, 0, 0, 0,232, 69,163, 3, 0, 0, 0, 0,232, 69,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,168,145,208, 3, 0, 0, 0, 0, 8,231,207, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 1, 0, 0,200, 0,209, 3, 0, 0, 0, 0,183, 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, - 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,120,243,211, 15, 0, 0, 0, 0,120,243,211, 15, 0, 0, 0, 0,136, 17,214, 3, 0, 0, 0, 0, - 0,115,101, 32, 83, 99,117,108,112,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, 1, 0, 0, 0, 68, 65, 84, 65, 16, 0, 0, 0, -136, 17,214, 3, 0, 0, 0, 0,237, 0, 0, 0, 1, 0, 0, 0, 42, 11, 0, 0, 42, 11, 0, 0,136,139,215, 3, 0, 0, 0, 0, - 68, 65, 84, 65,160,178, 0, 0,136,139,215, 3, 0, 0, 0, 0,236, 0, 0, 0, 42, 11, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, -168,194,217, 3, 0, 0, 0, 0, 19, 0, 0, 0, 1, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 20, 0, 0, 0, 1, 0, 1, 0, -168,194,217, 3, 0, 0, 0, 0, 21, 0, 1, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 24, 51,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,184,219,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, -136, 48,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,152, 7,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, -216, 29,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,168,225,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, -120,209,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,200,213,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 24, 98,200, 3, 0, 0, 0, 0, 21, 0, 0, 0, 1, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, -200, 66,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 30, 0,255,255, 3, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,136, 7,214, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, - 8,156,214, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,248, 9,215, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -152, 66,216, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 56, 43,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -232,117,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 24,157,217, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 8, 78,210, 3, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, - 40, 77,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -200, 85,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -104, 94,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, - 8,103,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -168,111,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, - 72,120,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -232,128,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -136,137,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -104,176,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, - 72,183,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, - 40,190,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, - 8,197,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -232,203,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -200,210,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -168,217,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -136,224,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -184,212,210, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -200,219,210, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -216,226,210, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -232,233,210, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -248,240,210, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -152,231,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -168,238,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -184,245,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -200,252,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -216, 3,219, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -232, 10,219, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -248, 17,219, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, - 8, 25,219, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, - 24, 98,200, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -120,209,217, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,120,209,217, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 70, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 71, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 72, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 73, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 74, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 75, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 76, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 77, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 78, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 79, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 80, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 81, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 82, 0, 1, 0, 0, 0, -152, 7,218, 3, 0, 0, 0, 0, 31, 0, 83, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, -136, 48,218, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 70, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 71, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 72, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 73, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 74, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 75, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 76, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 77, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 78, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 79, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 80, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 81, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 82, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 83, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 84, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 85, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 86, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 87, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 88, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 89, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 90, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 91, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 92, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 93, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 94, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 95, 0, 1, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 31, 0, 96, 0, 1, 0, 0, 0, -200,213,217, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 70, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 71, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 72, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 73, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 74, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 75, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 76, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 77, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 78, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 79, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 80, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 81, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 82, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 83, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 84, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 85, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 86, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 87, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 88, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 89, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 90, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 91, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 92, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 93, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 94, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 95, 0, 1, 0, 0, 0, -184,219,217, 3, 0, 0, 0, 0, 31, 0, 96, 0, 1, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 70, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 71, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 72, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 73, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 74, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 75, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 76, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 77, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 78, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 79, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 80, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 81, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 82, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 83, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 84, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 85, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 86, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 87, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 88, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 89, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 90, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 91, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 92, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 93, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 94, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 95, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0, 31, 0, 96, 0, 1, 0, 0, 0, -168,225,217, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,136, 7,214, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -136, 7,214, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,136, 7,214, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -136, 7,214, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,136, 7,214, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -136, 7,214, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,136, 7,214, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -136, 7,214, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,136, 7,214, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -136, 7,214, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 8,156,214, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 8,156,214, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 8,156,214, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 8,156,214, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 8,156,214, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 8,156,214, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 8,156,214, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 8,156,214, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 8,156,214, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 8,156,214, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,248, 9,215, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -248, 9,215, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,248, 9,215, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -248, 9,215, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,248, 9,215, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -248, 9,215, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,248, 9,215, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -248, 9,215, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,248, 9,215, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -248, 9,215, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,152, 66,216, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -152, 66,216, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,152, 66,216, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -152, 66,216, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,152, 66,216, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -152, 66,216, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,152, 66,216, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -152, 66,216, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,152, 66,216, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -152, 66,216, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 56, 43,217, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,232,117,217, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -232,117,217, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,232,117,217, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -232,117,217, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,232,117,217, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -232,117,217, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,232,117,217, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -232,117,217, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,232,117,217, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -232,117,217, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 24,157,217, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 24,157,217, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 24,157,217, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 24,157,217, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 24,157,217, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 24,157,217, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 24,157,217, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 24,157,217, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 24,157,217, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 24,157,217, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, -216, 29,218, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, - 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, - 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, - 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, - 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, - 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, - 8, 78,210, 3, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, - 24, 51,163, 3, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, - 56, 16,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 15,215, 3, 0, 0, 0, 0, -232, 35,201, 3, 0, 0, 0, 0, 40, 32,201, 3, 0, 0, 0, 0, 8, 34,201, 3, 0, 0, 0, 0,136, 36,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 4, 0, 0, 85, 0, 0, 0,150, 2, 0, 0, 1, 1,112, 4, 66, 2, 1, 0, - 0, 0, 0, 0, 0, 0, 8, 0,232,105,177, 3, 0, 0, 0, 0,152, 92,215, 3, 0, 0, 0, 0,152, 92,215, 3, 0, 0, 0, 0, - 24,111,215, 3, 0, 0, 0, 0,216,117,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 24,214,207, 3, 0, 0, 0, 0, 88,210,207, 3, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 24,111,215, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,200,112,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,108, 68, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,142, 68, 0, 0, 0, 0, 0, 0,208, 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,111, 4, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0,224,141, 68, 0, 0,200, 65, 0,224,141, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,112, 4, 26, 0,112, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 4, 0, 0, 85, 0, 0, 0,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,112, 4, 26, 0, 10, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 88,199,177, 3, 0, 0, 0, 0,248, 77,163, 3, 0, 0, 0, 0,248, 77,163, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,233,207, 3, 0, 0, 0, 0,120,238,207, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,200,112,215, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,120,114,215, 3, 0, 0, 0, 0, 24,111,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, - 0,192, 5,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 0,168,195, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, - 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, - 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, - 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0, 80, 1,143, 0, 80, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0, 71, 1, 0, 0,150, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 80, 1, 11, 0, 5, 0, 3, 0, 0, 0, 0, 0, 0, 0,160, 0, 50, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 88,195,177, 3, 0, 0, 0, 0,136, 64,163, 3, 0, 0, 0, 0,136, 64,163, 3, 0, 0, 0, 0, -152, 77,215, 3, 0, 0, 0, 0, 8,165,165, 15, 0, 0, 0, 0,136,239,207, 3, 0, 0, 0, 0,184,242,207, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,152, 77,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,120, 79,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,235,223, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, 99,116,109,111, -100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, 99,116,109,111, -100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 79, 98,106,101, 99,116, 32, 84,111,111,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,233,253,143, 0,255, 1, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0,120, 79,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 88, 81,215, 3, 0, 0, 0, 0, -152, 77,215, 3, 0, 0, 0, 0,136, 0,225, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,114,117,115,104, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 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,254,143, 0,115, 1, - 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 88, 81,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 56, 83,215, 3, 0, 0, 0, 0,120, 79,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95,116,111, -111,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95,116,111, -111,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84,111,111,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74,254,143, 0, 61, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0, 56, 83,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 24, 85,215, 3, 0, 0, 0, 0, - 88, 81,215, 3, 0, 0, 0, 0,200, 3,225, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95,115,116,114,111,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95,115,116,114,111,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,116,114,111,107,101, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,254,143, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 24, 85,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,248, 86,215, 3, 0, 0, 0, 0, 56, 83,215, 3, 0, 0, 0, 0,104, 5,225, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95, 99,117, -114,118,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95, 99,117, -114,118,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 67,117,114,118,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45,254,143, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0,248, 86,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,216, 88,215, 3, 0, 0, 0, 0, - 24, 85,215, 3, 0, 0, 0, 0, 72, 10,225, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95, 97,112,112,101, 97,114, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95, 97,112,112,101, 97,114, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,112,112,101, 97,114, 97,110, - 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,229,253,143, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,216, 88,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,200,168,165, 15, 0, 0, 0, 0,248, 86,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,118,101,114,116,101,120,112, 97, -105,110,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, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,118,101,114,116,101,120,112, 97, -105,110,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, 79,112,116,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,149,253,143, 0,146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0,200,168,165, 15, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,232,166,165, 15, 0, 0, 0, 0, -216, 88,215, 3, 0, 0, 0, 0, 40, 2,225, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95,116,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95,116,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,101,120,116,117,114,101, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93,254,143, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 4, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,232,166,165, 15, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 8,165,165, 15, 0, 0, 0, 0,200,168,165, 15, 0, 0, 0, 0, 8, 7,225, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,115, 99,117,108,112,116, 95,111,112,116,105,111,110,115, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,115, 99,117,108,112,116, 95,111,112,116,105,111,110,115, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 79,112,116,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21,254,143, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0, 8,165,165, 15, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -232,166,165, 15, 0, 0, 0, 0,168, 8,225, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,115, 99,117,108,112,116, 95,115,121,109,109,101,116,114,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95,115, 99,117,108,112,116, 95,115,121,109,109,101,116,114,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,121,109,109,101,116,114,121, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253,253,143, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 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, 68, 65, 84, 65, 40, 1, 0, 0,120,114,215, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 40,116,215, 3, 0, 0, 0, 0,200,112,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, - 0, 0, 90,195, 0, 0, 0, 0, 0, 0, 0, 0,227,102, 16, 67, 24, 30, 90,195, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, - 0, 0, 0, 0,215, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, - 0, 0, 0, 0,215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, - 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,216, 0,143, 0,216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0,111, 0, 0, 0, 70, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,160, 0,216, 0, 12, 0, 6, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,136,196,177, 3, 0, 0, 0, 0, 88, 83,163, 3, 0, 0, 0, 0, 88, 83,163, 3, 0, 0, 0, 0, -184, 90,215, 3, 0, 0, 0, 0,184, 90,215, 3, 0, 0, 0, 0,200,243,207, 3, 0, 0, 0, 0,248,246,207, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,184, 90,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,197,177, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 99,117,108,112,116, 32, 77,111,100,101, 0, 32, 77,111,100,101, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,255,144, 0, 16, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 40, 1, 0, 0, 40,116,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216,117,215, 3, 0, 0, 0, 0, -120,114,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 67, 0, 96,158,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, - 0, 96,158,196, 0,128,142,195,163, 0, 0, 0,180, 0, 0, 0, 0, 0, 0, 0,213, 3, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0,213, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,180, 0, -214, 3,163, 0,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 4, 0, 0,111, 4, 0, 0, -111, 0, 0, 0,150, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 0, - 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,189,177, 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, - 68, 65, 84, 65, 40, 1, 0, 0,216,117,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 40,116,215, 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,160, 0, 0, 0,111, 4, 0, 0, -111, 0, 0, 0,150, 2, 0, 0,160, 0, 0, 0,111, 4, 0, 0,111, 0, 0, 0,150, 2, 0, 0,208, 3, 40, 2, 13, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,188,177, 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, - 40,151,207, 3, 0, 0, 0, 0,168, 34,208, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 62,216, 3, 0, 0, 0, 0, - 68, 65, 84, 65,112, 3, 0, 0,168, 62,216, 3, 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71,137,247, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -142, 6,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0, 11,210, 76,190, 0, 0, 0, 0, 68,239,209, 62, 51,177,205,190, -184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, - 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33,210,111,193, 0, 0,128, 63, 68,239,209, 62, 70,119,105, 63, -176, 84, 89,188, 0, 0, 0, 0, 52,177,205,190,142, 74, 70, 62,166, 33,101, 63, 0, 0, 0, 0,185,158, 81, 63, 35, 44,185,190, - 43, 61,228, 62, 0, 0, 0, 0, 62, 95, 68, 65, 51,120,173,192,115,208,213, 64, 0, 0,128, 63,178,157,229, 62, 69,228, 70,191, -116,169, 81,191,184,158, 81,191,117, 90,127, 63, 69,188,191, 62,158, 53,185, 62, 35, 44,185, 62,145,180,109,188, 86,142,221, 63, -218, 72,228,190, 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0, 33,171,108, 65, 33,210,111, 65,100,240,191, 62,110,116, 85, 63, - 48,185, 70,188, 0, 0, 82,180,137,185, 84,190, 30, 18,205, 61, 77,247,236, 62, 0, 0, 40, 51,197,112,117,194,178,208,216, 65, -220,158, 5,194,231,251,159,192,221, 54,114, 66, 29,247,213,193, 58,221, 3, 66, 25, 4,160, 64, 68,239,209, 62, 51,177,205,190, -184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, - 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33,210,111,193, 0, 0,128, 63,178,157,229, 62, 69,228, 70,191, -116,169, 81,191,184,158, 81,191,117, 90,127, 63, 69,188,191, 62,158, 53,185, 62, 35, 44,185, 62,145,180,109,188, 86,142,221, 63, -218, 72,228,190, 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0, 33,171,108, 65, 33,210,111, 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, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,203, 6, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,203, 6, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 60,203, 6, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 92, 62, 55, 63, 56,186,224,190, -237,203,148,190, 3,236,234,190, 33,210,111, 65, 33,210,111, 65, 0, 0, 0, 0, 0, 0, 0, 0,114,145,245, 58, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 32, 33, 12, 66, 85,152,137, 66,113, 27,126, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 1, 0, 0,152, 92,215, 3, 0, 0, 0, 0,174, 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, - 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65,205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0, -200,213,217, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, - 8, 24,128, 0, 0, 0, 12, 66, 0, 0,128, 63,205,204,204, 61, 0, 0,122, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 10, 0, 7, 1, 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, - 83, 78, 0, 0, 8, 1, 0, 0,152, 66,216, 3, 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0, 56, 43,217, 3, 0, 0, 0, 0, -248, 9,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 71, 97,109,101, 32, 76, -111,103,105, 99, 0, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 37,201, 3, 0, 0, 0, 0, 72, 45,201, 3, 0, 0, 0, 0, - 40,136,171, 3, 0, 0, 0, 0,184, 80,216, 3, 0, 0, 0, 0, 88, 17,215, 3, 0, 0, 0, 0,248, 22,215, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 32, 0, 0, 0, 40, 37,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200, 37,201, 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, 68, 65, 84, 65, 32, 0, 0, 0, -200, 37,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104, 38,201, 3, 0, 0, 0, 0, 40, 37,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,104, 38,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0, 8, 39,201, 3, 0, 0, 0, 0,200, 37,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -126, 7, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8, 39,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -168, 39,201, 3, 0, 0, 0, 0,104, 38,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0,168, 39,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 40,201, 3, 0, 0, 0, 0, - 8, 39,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, - 72, 40,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232, 40,201, 3, 0, 0, 0, 0,168, 39,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,126, 7,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,232, 40,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0,136, 41,201, 3, 0, 0, 0, 0, 72, 40,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,136, 41,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, - 40, 42,201, 3, 0, 0, 0, 0,232, 40,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6,140, 1, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0, 40, 42,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200, 42,201, 3, 0, 0, 0, 0, -136, 41,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -200, 42,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104, 43,201, 3, 0, 0, 0, 0, 40, 42,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,126, 7,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,104, 43,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0, 8, 44,201, 3, 0, 0, 0, 0,200, 42,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 64, 5,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8, 44,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -168, 44,201, 3, 0, 0, 0, 0,104, 43,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 5,234, 3, 1, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0,168, 44,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 45,201, 3, 0, 0, 0, 0, - 8, 44,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 1,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, - 72, 45,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 44,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 1,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,136,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,216,136,171, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 37,201, 3, 0, 0, 0, 0, -104, 38,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,136,171, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 88, 68,216, 3, 0, 0, 0, 0, 40,136,171, 3, 0, 0, 0, 0,200, 37,201, 3, 0, 0, 0, 0, -168, 39,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88, 68,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 8, 69,216, 3, 0, 0, 0, 0,216,136,171, 3, 0, 0, 0, 0,104, 38,201, 3, 0, 0, 0, 0, - 72, 40,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8, 69,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,184, 69,216, 3, 0, 0, 0, 0, 88, 68,216, 3, 0, 0, 0, 0,168, 39,201, 3, 0, 0, 0, 0, - 72, 40,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184, 69,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,104, 70,216, 3, 0, 0, 0, 0, 8, 69,216, 3, 0, 0, 0, 0,168, 39,201, 3, 0, 0, 0, 0, -232, 40,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104, 70,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 24, 71,216, 3, 0, 0, 0, 0,184, 69,216, 3, 0, 0, 0, 0,232, 40,201, 3, 0, 0, 0, 0, -136, 41,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24, 71,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,200, 71,216, 3, 0, 0, 0, 0,104, 70,216, 3, 0, 0, 0, 0, 8, 39,201, 3, 0, 0, 0, 0, - 40, 42,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200, 71,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,120, 72,216, 3, 0, 0, 0, 0, 24, 71,216, 3, 0, 0, 0, 0,136, 41,201, 3, 0, 0, 0, 0, - 40, 42,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120, 72,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 40, 73,216, 3, 0, 0, 0, 0,200, 71,216, 3, 0, 0, 0, 0, 40, 37,201, 3, 0, 0, 0, 0, -232, 40,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40, 73,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,216, 73,216, 3, 0, 0, 0, 0,120, 72,216, 3, 0, 0, 0, 0, 40, 37,201, 3, 0, 0, 0, 0, - 40, 42,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216, 73,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,136, 74,216, 3, 0, 0, 0, 0, 40, 73,216, 3, 0, 0, 0, 0, 72, 40,201, 3, 0, 0, 0, 0, -200, 42,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136, 74,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 56, 75,216, 3, 0, 0, 0, 0,216, 73,216, 3, 0, 0, 0, 0, 8, 39,201, 3, 0, 0, 0, 0, -200, 42,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56, 75,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,232, 75,216, 3, 0, 0, 0, 0,136, 74,216, 3, 0, 0, 0, 0,136, 41,201, 3, 0, 0, 0, 0, -200, 42,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232, 75,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,152, 76,216, 3, 0, 0, 0, 0, 56, 75,216, 3, 0, 0, 0, 0,104, 43,201, 3, 0, 0, 0, 0, - 8, 44,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,152, 76,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 72, 77,216, 3, 0, 0, 0, 0,232, 75,216, 3, 0, 0, 0, 0, 72, 40,201, 3, 0, 0, 0, 0, - 8, 44,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72, 77,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,248, 77,216, 3, 0, 0, 0, 0,152, 76,216, 3, 0, 0, 0, 0,200, 42,201, 3, 0, 0, 0, 0, -104, 43,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248, 77,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,168, 78,216, 3, 0, 0, 0, 0, 72, 77,216, 3, 0, 0, 0, 0,232, 40,201, 3, 0, 0, 0, 0, -168, 44,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168, 78,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 88, 79,216, 3, 0, 0, 0, 0,248, 77,216, 3, 0, 0, 0, 0,104, 43,201, 3, 0, 0, 0, 0, -168, 44,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88, 79,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 8, 80,216, 3, 0, 0, 0, 0,168, 78,216, 3, 0, 0, 0, 0,168, 39,201, 3, 0, 0, 0, 0, - 72, 45,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8, 80,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0,184, 80,216, 3, 0, 0, 0, 0, 88, 79,216, 3, 0, 0, 0, 0, 8, 44,201, 3, 0, 0, 0, 0, - 72, 45,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184, 80,216, 3, 0, 0, 0, 0, -212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 80,216, 3, 0, 0, 0, 0,168, 44,201, 3, 0, 0, 0, 0, - 72, 45,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 88, 17,215, 3, 0, 0, 0, 0, -214, 0, 0, 0, 1, 0, 0, 0,120, 18,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 39,201, 3, 0, 0, 0, 0, -200, 37,201, 3, 0, 0, 0, 0,104, 38,201, 3, 0, 0, 0, 0, 72, 40,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,126, 7, 0, 0,235, 3, 0, 0, 5, 4, 0, 0, 7, 7,127, 7, 27, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,216,199,207, 3, 0, 0, 0, 0,216,199,207, 3, 0, 0, 0, 0,136,119,215, 3, 0, 0, 0, 0, - 56,121,215, 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, 68, 65, 84, 65, 40, 1, 0, 0,136,119,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, - 56,121,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,148, 68, 0, 0, 0, 0, 0, 0,208, 65, - 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, - 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, - 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,126, 7, 0, 0,235, 3, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56,121,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,136,119,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,109, 69, 0, 0,128,192, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,238, 68, 0, 0, 0, 0, 0, 0, 0, 64,112, 7, 0, 0,129, 7, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 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,128, 63, 0, 0,128, 63, 2, 0, 0, 0, 1, 0, 3, 3, - 2, 0, 0, 4, 10, 0,129, 7, 2, 0,112, 7, 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, 5, 4, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65,160, 0, 0, 0,120, 18,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, -152, 19,215, 3, 0, 0, 0, 0, 88, 17,215, 3, 0, 0, 0, 0, 40, 42,201, 3, 0, 0, 0, 0,136, 41,201, 3, 0, 0, 0, 0, -200, 42,201, 3, 0, 0, 0, 0, 8, 39,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, - 0, 0, 0, 0,139, 1, 0, 0, 4, 4, 94, 1,140, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 56,128,199, 3, 0, 0, 0, 0, 56,128,199, 3, 0, 0, 0, 0,232,122,215, 3, 0, 0, 0, 0,152,124,215, 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, - 68, 65, 84, 65, 40, 1, 0, 0,232,122,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,152,124,215, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,175, 67, - 0, 0, 0, 0, 0, 0,208, 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, 93, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,174, 67, 0, 0,200, 65, - 0,128,174, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 94, 1, - 26, 0, 94, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, -114, 1, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 1, 26, 0, 0, 0, 1, 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, - 68, 65, 84, 65, 40, 1, 0, 0,152,124,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -232,122,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,174, 67, 0, 0, 61,196, 0, 0, 0, 0, 0, 0, 0, 0,255,127,166, 67, -255,255,184,195, 0, 0, 0, 0, 77, 1, 0, 0, 94, 1, 0, 0, 0, 0, 0, 0,113, 1, 0, 0, 0, 0, 0, 0, 78, 1, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 0, 0,113, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0, 94, 1, -114, 1, 77, 1,114, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, - 0, 0, 0, 0,113, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 1,114, 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,120, 94,215, 3, 0, 0, 0, 0,184,205,216, 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, - 68, 65, 84, 65, 88, 1, 0, 0,120, 94,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 88, 96,215, 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, 66, 85, 84, 84, 79, 78, 83, 95, - 80, 84, 95, 99,111,110,116,101,120,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, 66, 85, 84, 84, 79, 78, 83, 95, - 80, 84, 95, 99,111,110,116,101,120,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, 67,111,110,116,101,120,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,220,255, 76, 1, 36, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 88, 96,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 56, 98,215, 3, 0, 0, 0, 0,120, 94,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255, 76, 1, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0, 56, 98,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 24,100,215, 3, 0, 0, 0, 0, - 88, 96,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,121,101,114,115, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 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,255, 76, 1, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 24,100,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,248,101,215, 3, 0, 0, 0, 0, 56, 98,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140,254, 76, 1,203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, - 68, 65, 84, 65, 88, 1, 0, 0,248,101,215, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,216,103,215, 3, 0, 0, 0, 0, - 24,100,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,110,116,105, 45, 65,108,105, - 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58,254, 76, 1, 58, 0, - 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,216,103,215, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 88,196,216, 3, 0, 0, 0, 0,248,101,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 97,109,112,108,101,100, 32, 77,111,116,105,111,110, 32, 66,108,117,114, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,254, 76, 1, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0, 88,196,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 56,198,216, 3, 0, 0, 0, 0, -216,103,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,104, 97,100,105,110,103, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,254, 76, 1, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 56,198,216, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 24,200,216, 3, 0, 0, 0, 0, 88,196,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,242,253, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0, 24,200,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,248,201,216, 3, 0, 0, 0, 0, - 56,198,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,111,115,116, 32, 80,114,111, - 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,218,253, 76, 1, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,248,201,216, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0,216,203,216, 3, 0, 0, 0, 0, 24,200,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194,253, 76, 1, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 88, 1, 0, 0,216,203,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,184,205,216, 3, 0, 0, 0, 0, -248,201,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,111,117,116,112,117,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, 82, 69, 78, 68, 69, 82, 95, 80, - 84, 95,111,117,116,112,117,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, 79,117,116,112,117,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, 40,253, 76, 1,130, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,184,205,216, 3, 0, 0, 0, 0, -213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,203,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,253, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,248, 0, 0, 0, 56,128,199, 3, 0, 0, 0, 0,179, 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, 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, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 21, 0, 0,160, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,152, 19,215, 3, 0, 0, 0, 0, -214, 0, 0, 0, 1, 0, 0, 0,184, 20,215, 3, 0, 0, 0, 0,120, 18,215, 3, 0, 0, 0, 0, 40, 37,201, 3, 0, 0, 0, 0, -232, 40,201, 3, 0, 0, 0, 0,136, 41,201, 3, 0, 0, 0, 0, 40, 42,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 6, 0, 0, 0, 0, 0, 0,139, 1, 0, 0, 17, 17, 32, 6,140, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,248,217,208, 3, 0, 0, 0, 0,248,217,208, 3, 0, 0, 0, 0, 72,126,215, 3, 0, 0, 0, 0, -168,129,215, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72,126,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, -248,127,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 67, 0, 0, 0, 0, 0, 0,208, 65, - 0, 0, 0, 0, 0, 0,196, 68, 0, 0, 0, 0, 0, 0,208, 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, 31, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, - 0,224,195, 68, 0, 0,200, 65, 0,224,195, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, - 4, 0, 12, 0, 10, 0, 32, 6, 26, 0, 32, 6, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 32, 6, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,248,127,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, -168,129,215, 3, 0, 0, 0, 0, 72,126,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 67, 0, 0,185,195, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 75, 67, 0, 0,185,195, 0, 0, 0, 0,203, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0,113, 1, 0, 0, - 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0,113, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, - 18, 0, 0, 4, 6, 0,220, 0,114, 1,203, 0,114, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,219, 0, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -220, 0,114, 1, 0, 0, 4, 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,152,207,216, 3, 0, 0, 0, 0, -152,207,216, 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, 68, 65, 84, 65, 88, 1, 0, 0,152,207,216, 3, 0, 0, 0, 0,213, 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, - 76, 79, 71, 73, 67, 95, 80, 84, 95,112,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 76, 79, 71, 73, 67, 95, 80, 84, 95,112,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,196,255,203, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, -168,129,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,127,215, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,160, 68, 0, 0, 0, 0, 0, 0,112, 67, 0, 80, 31,195, 0,234,179, 68,224,198,182,194,184,177,165, 67, - 51, 5, 0, 0, 68, 5, 0, 0, 18, 0, 0, 0,113, 1, 0, 0, 0, 0, 0, 0, 50, 5, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0, 50, 5, 0, 0, 18, 0, 0, 0,113, 1, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,250, 70, 0, 0,250, 70, - 0, 0, 0, 63, 72,225,154, 63, 10, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 68, 5,114, 1, 51, 5, 96, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0, 0, 0, 31, 6, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 5,114, 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, 68, 65, 84, 65, 72, 0, 0, 0, -248,217,208, 3, 0, 0, 0, 0,192, 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, 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,255, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, -184, 20,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,216, 21,215, 3, 0, 0, 0, 0,152, 19,215, 3, 0, 0, 0, 0, -104, 43,201, 3, 0, 0, 0, 0, 8, 44,201, 3, 0, 0, 0, 0, 72, 40,201, 3, 0, 0, 0, 0,200, 42,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 65, 5, 0, 0,126, 7, 0, 0,141, 1, 0, 0,233, 3, 0, 0, 9, 9, 62, 2, 93, 2, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,228,216, 3, 0, 0, 0, 0, 40,228,216, 3, 0, 0, 0, 0, - 88,131,215, 3, 0, 0, 0, 0, 8,133,215, 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, 68, 65, 84, 65, 40, 1, 0, 0, 88,131,215, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 8,133,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230, 67, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,128, 15, 68, 0, 0, 0, 0, 0, 0,208, 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, 61, 2, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0, 64, 15, 68, 0, 0,200, 65, 0, 64, 15, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 62, 2, 26, 0, 62, 2, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 65, 5, 0, 0,126, 7, 0, 0,141, 1, 0, 0,166, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 62, 2, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8,133,215, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,131,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,181, 67, - 0, 0, 0, 0, 0,128,218, 67, 0, 0, 0, 0,131,248, 1, 68, 0, 0, 0, 0, 86, 26, 3, 68, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 2, 0, 0, - 0, 0, 0, 0, 66, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,215, 35, 60, 0, 0,122, 68, - 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 4, 10, 0, 62, 2, 67, 2, 62, 2, 67, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 65, 5, 0, 0,126, 7, 0, 0,167, 1, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 62, 2, 67, 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, 68, 65, 84, 65,160, 2, 0, 0, 40,228,216, 3, 0, 0, 0, 0, -186, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,216, 21,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, -248, 22,215, 3, 0, 0, 0, 0,184, 20,215, 3, 0, 0, 0, 0,168, 44,201, 3, 0, 0, 0, 0, 72, 45,201, 3, 0, 0, 0, 0, - 8, 44,201, 3, 0, 0, 0, 0,104, 43,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 63, 5, 0, 0, -141, 1, 0, 0,233, 3, 0, 0, 1, 1,251, 3, 93, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -120,209,216, 3, 0, 0, 0, 0,120,209,216, 3, 0, 0, 0, 0,184,134,215, 3, 0, 0, 0, 0,216,234,216, 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, - 68, 65, 84, 65, 40, 1, 0, 0,184,134,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,104,136,215, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,113, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,192,126, 68, - 0, 0, 0, 0, 0, 0,208, 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,250, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,126, 68, 0, 0,200, 65, - 0,128,126, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,251, 3, - 26, 0,251, 3, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 63, 5, 0, 0, -141, 1, 0, 0,166, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,251, 3, 26, 0, 0, 0, 1, 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, - 68, 65, 84, 65, 40, 1, 0, 0,104,136,215, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,120,231,216, 3, 0, 0, 0, 0, -184,134,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 64, 70,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, -255,127, 70,196, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0, - 44, 3,143, 0, 26, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, -167, 1, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 67, 2, 0, 0, 5, 0, - 3, 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, - 68, 65, 84, 65, 40, 1, 0, 0,120,231,216, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 40,233,216, 3, 0, 0, 0, 0, -104,136,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 67, 0, 0,206,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, - 0, 0,206,194, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0, -120, 0,143, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 63, 5, 0, 0, -167, 1, 0, 0,167, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 6, 0, - 34, 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, - 68, 65, 84, 65, 40, 1, 0, 0, 40,233,216, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216,234,216, 3, 0, 0, 0, 0, -120,231,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 67, 0, 0,109,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, - 0, 0,109,196, 0,128,145,195,163, 0, 0, 0,180, 0, 0, 0, 0, 0, 0, 0,144, 2, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0,144, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,180, 0, -145, 2,163, 0,145, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 5, 0, 0, 63, 5, 0, 0, -167, 1, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, - 68, 65, 84, 65, 40, 1, 0, 0,216,234,216, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 40,233,216, 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, 69, 1, 0, 0, 63, 5, 0, 0, -167, 1, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,251, 3, 67, 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, 72, 7,217, 3, 0, 0, 0, 0, - 68, 65, 84, 65,112, 3, 0, 0, 72, 7,217, 3, 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0,190, 35, 30, 61, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 40,139, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,190, 35, 30, 61, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 40,139, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,149, 53,207, 65, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112,121,107, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -255,255,249,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,190, 35, 30, 61, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 40,139, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,207, 3,116, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,207, 3,116, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -207, 3,116, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,149, 53,207, 65,214,211,111, 65, 0, 0, 0, 0, 0, 0, 0, 0,221, 57, 80, 61, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 65, 0, 0, 5, 0,251,251, 0, 0, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, - 3,236,234,190, 1, 0, 0, 0, 0, 0,128, 63, 0, 0,180, 66, 0, 0,180, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 1, 0, 0,120,209,216, 3, 0, 0, 0, 0,174, 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, - 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65,205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0, -200,213,217, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, - 8, 8,128, 0, 0, 0, 12, 66, 0, 0,128, 63,205,204,204, 61, 0, 0,122, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 10, 0, 7, 1, 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, - 68, 65, 84, 65,160, 0, 0, 0,248, 22,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -216, 21,215, 3, 0, 0, 0, 0,232, 40,201, 3, 0, 0, 0, 0,168, 39,201, 3, 0, 0, 0, 0, 72, 45,201, 3, 0, 0, 0, 0, -168, 44,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 1, 0, 0,141, 1, 0, 0,233, 3, 0, 0, - 3, 3, 68, 1, 93, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 2,209, 3, 0, 0, 0, 0, -104, 2,209, 3, 0, 0, 0, 0,136,236,216, 3, 0, 0, 0, 0, 56,238,216, 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, 68, 65, 84, 65, 40, 1, 0, 0, -136,236,216, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 56,238,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,128,244, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,162, 67, 0, 0, 0, 0, 0, 0,208, 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, 67, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,161, 67, 0, 0,200, 65, 0,128,161, 67, 0, 0,200, 65, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 68, 1, 26, 0, 68, 1, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 1, 0, 0,141, 1, 0, 0,166, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, - 56,238,216, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,236,216, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0,128,141, 67, 0, 0,244,194, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,153, 67, 0, 64, 12,196, 0, 0, 0, 0, - 51, 1, 0, 0, 68, 1, 0, 0, 18, 0, 0, 0, 66, 2, 0, 0, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 0, 0, 0, 50, 1, 0, 0, 18, 0, 0, 0, 66, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 18, 6, 0, 0, 2, 0, 3, 3, 0, 0, 12, 4, 6, 0, 68, 1, 67, 2, 51, 1, 49, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 1, 0, 0,167, 1, 0, 0,233, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 1, 67, 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, 68, 65, 84, 65, 24, 1, 0, 0, -104, 2,209, 3, 0, 0, 0, 0,183, 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, 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,104, 11,217, 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, 1, 0, 0, 0, 68, 65, 84, 65, 16, 0, 0, 0,104, 11,217, 3, 0, 0, 0, 0,237, 0, 0, 0, 1, 0, 0, 0, - 14, 0, 0, 0, 14, 0, 0, 0, 88, 32,199, 3, 0, 0, 0, 0, 68, 65, 84, 65,224, 0, 0, 0, 88, 32,199, 3, 0, 0, 0, 0, -236, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 19, 0, 0, 0, 1, 0, 1, 0, -168,194,217, 3, 0, 0, 0, 0, 20, 0, 0, 0, 1, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 21, 0, 1, 0, 1, 0, 0, 0, -168,194,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 24, 51,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, -184,219,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,136, 48,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, -152, 7,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,216, 29,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, -168,225,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,120,209,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, -200,213,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 24, 98,200, 3, 0, 0, 0, 0, 21, 0, 0, 0, 1, 0, 1, 0, -168,194,217, 3, 0, 0, 0, 0, 83, 78, 0, 0, 8, 1, 0, 0, 56, 43,217, 3, 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0, -232,117,217, 3, 0, 0, 0, 0,152, 66,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 83, 82, 83, 99,114,105,112,116,105,110,103, 0,103, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232, 45,201, 3, 0, 0, 0, 0, - 8, 54,201, 3, 0, 0, 0, 0,104, 81,216, 3, 0, 0, 0, 0,216, 95,216, 3, 0, 0, 0, 0, 24, 24,215, 3, 0, 0, 0, 0, -184, 29,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 32, 0, 0, 0,232, 45,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -136, 46,201, 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, - 68, 65, 84, 65, 32, 0, 0, 0,136, 46,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40, 47,201, 3, 0, 0, 0, 0, -232, 45,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, - 40, 47,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200, 47,201, 3, 0, 0, 0, 0,136, 46,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,200, 47,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0,104, 48,201, 3, 0, 0, 0, 0, 40, 47,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -126, 7, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,104, 48,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, - 8, 49,201, 3, 0, 0, 0, 0,200, 47,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 3, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0, 8, 49,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,168, 49,201, 3, 0, 0, 0, 0, -104, 48,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,168, 3, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, -168, 49,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 50,201, 3, 0, 0, 0, 0, 8, 49,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,240, 5,168, 3, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 72, 50,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0,232, 50,201, 3, 0, 0, 0, 0,168, 49,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 5, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,232, 50,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, -136, 51,201, 3, 0, 0, 0, 0, 72, 50,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 1, 1, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0,136, 51,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40, 52,201, 3, 0, 0, 0, 0, -232, 50,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 5,104, 1, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, - 40, 52,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200, 52,201, 3, 0, 0, 0, 0,136, 51,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,248, 2,104, 1, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,200, 52,201, 3, 0, 0, 0, 0, -211, 0, 0, 0, 1, 0, 0, 0,104, 53,201, 3, 0, 0, 0, 0, 40, 52,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 5,236, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,104, 53,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, - 8, 54,201, 3, 0, 0, 0, 0,200, 52,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,236, 2, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0, 8, 54,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -104, 53,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 2,168, 3, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -104, 81,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24, 82,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -136, 46,201, 3, 0, 0, 0, 0, 40, 47,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 24, 82,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200, 82,216, 3, 0, 0, 0, 0,104, 81,216, 3, 0, 0, 0, 0, -136, 46,201, 3, 0, 0, 0, 0,104, 48,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -200, 82,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120, 83,216, 3, 0, 0, 0, 0, 24, 82,216, 3, 0, 0, 0, 0, - 40, 47,201, 3, 0, 0, 0, 0, 8, 49,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -120, 83,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40, 84,216, 3, 0, 0, 0, 0,200, 82,216, 3, 0, 0, 0, 0, -104, 48,201, 3, 0, 0, 0, 0, 8, 49,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 40, 84,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216, 84,216, 3, 0, 0, 0, 0,120, 83,216, 3, 0, 0, 0, 0, - 8, 49,201, 3, 0, 0, 0, 0,168, 49,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -216, 84,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136, 85,216, 3, 0, 0, 0, 0, 40, 84,216, 3, 0, 0, 0, 0, -200, 47,201, 3, 0, 0, 0, 0, 72, 50,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -136, 85,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56, 86,216, 3, 0, 0, 0, 0,216, 84,216, 3, 0, 0, 0, 0, -232, 45,201, 3, 0, 0, 0, 0,232, 50,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 56, 86,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232, 86,216, 3, 0, 0, 0, 0,136, 85,216, 3, 0, 0, 0, 0, -104, 48,201, 3, 0, 0, 0, 0,232, 50,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -232, 86,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152, 87,216, 3, 0, 0, 0, 0, 56, 86,216, 3, 0, 0, 0, 0, -168, 49,201, 3, 0, 0, 0, 0,136, 51,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -152, 87,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72, 88,216, 3, 0, 0, 0, 0,232, 86,216, 3, 0, 0, 0, 0, - 72, 50,201, 3, 0, 0, 0, 0,136, 51,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 72, 88,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248, 88,216, 3, 0, 0, 0, 0,152, 87,216, 3, 0, 0, 0, 0, -232, 50,201, 3, 0, 0, 0, 0, 40, 52,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -248, 88,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168, 89,216, 3, 0, 0, 0, 0, 72, 88,216, 3, 0, 0, 0, 0, -136, 51,201, 3, 0, 0, 0, 0, 40, 52,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -168, 89,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88, 90,216, 3, 0, 0, 0, 0,248, 88,216, 3, 0, 0, 0, 0, - 72, 50,201, 3, 0, 0, 0, 0,200, 52,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 88, 90,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8, 91,216, 3, 0, 0, 0, 0,168, 89,216, 3, 0, 0, 0, 0, -168, 49,201, 3, 0, 0, 0, 0,200, 52,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 8, 91,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184, 91,216, 3, 0, 0, 0, 0, 88, 90,216, 3, 0, 0, 0, 0, - 8, 49,201, 3, 0, 0, 0, 0,104, 53,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -184, 91,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104, 92,216, 3, 0, 0, 0, 0, 8, 91,216, 3, 0, 0, 0, 0, -200, 47,201, 3, 0, 0, 0, 0,104, 53,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -104, 92,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24, 93,216, 3, 0, 0, 0, 0,184, 91,216, 3, 0, 0, 0, 0, -200, 52,201, 3, 0, 0, 0, 0,104, 53,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 24, 93,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200, 93,216, 3, 0, 0, 0, 0,104, 92,216, 3, 0, 0, 0, 0, -104, 48,201, 3, 0, 0, 0, 0, 8, 54,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -200, 93,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120, 94,216, 3, 0, 0, 0, 0, 24, 93,216, 3, 0, 0, 0, 0, -168, 49,201, 3, 0, 0, 0, 0, 8, 54,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -120, 94,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40, 95,216, 3, 0, 0, 0, 0,200, 93,216, 3, 0, 0, 0, 0, - 40, 52,201, 3, 0, 0, 0, 0, 8, 54,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, - 40, 95,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216, 95,216, 3, 0, 0, 0, 0,120, 94,216, 3, 0, 0, 0, 0, -232, 50,201, 3, 0, 0, 0, 0,136, 51,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, -216, 95,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 95,216, 3, 0, 0, 0, 0, -232, 45,201, 3, 0, 0, 0, 0, 72, 50,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, - 24, 24,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 56, 25,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -104, 48,201, 3, 0, 0, 0, 0,136, 46,201, 3, 0, 0, 0, 0, 40, 47,201, 3, 0, 0, 0, 0, 8, 49,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,169, 3, 0, 0, 5, 4, 0, 0, 7, 7,127, 7, 93, 0, 1, 0, - 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,200,207, 3, 0, 0, 0, 0,152,200,207, 3, 0, 0, 0, 0, -232,239,216, 3, 0, 0, 0, 0,152,241,216, 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, 68, 65, 84, 65, 40, 1, 0, 0,232,239,216, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,152,241,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,148, 68, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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,126, 7, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,236, 3, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,152,241,216, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,239,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,239, 68, - 0, 0, 0, 0, 0, 0, 28, 66, 0, 0, 0, 0, 0,192,237, 68, 0, 0, 0, 0, 0, 0,134, 66,110, 7, 0, 0,127, 7, 0, 0, - 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,109, 7, 0, 0, - 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 2, 2, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,127, 7, 67, 0,110, 7, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,169, 3, 0, 0,235, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 56, 25,215, 3, 0, 0, 0, 0, -214, 0, 0, 0, 1, 0, 0, 0, 88, 26,215, 3, 0, 0, 0, 0, 24, 24,215, 3, 0, 0, 0, 0, 72, 50,201, 3, 0, 0, 0, 0, -200, 52,201, 3, 0, 0, 0, 0,104, 53,201, 3, 0, 0, 0, 0,200, 47,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -241, 5, 0, 0,126, 7, 0, 0, 0, 0, 0, 0,235, 2, 0, 0, 4, 4,142, 1,236, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,184,129,199, 3, 0, 0, 0, 0,184,129,199, 3, 0, 0, 0, 0, 72,243,216, 3, 0, 0, 0, 0, -248,244,216, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72,243,216, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, -248,244,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148, 67, 0, 0, 0, 0, 0, 0,208, 65, - 0, 0, 0, 0, 0, 0,199, 67, 0, 0, 0, 0, 0, 0,208, 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,141, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, - 0,128,198, 67, 0, 0,200, 65, 0,128,198, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, - 4, 0, 12, 0, 10, 0,142, 1, 26, 0,142, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -241, 5, 0, 0,126, 7, 0, 0,210, 2, 0, 0,235, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -142, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,248,244,216, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 72,243,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,198, 67, 0, 0, 61,196, 0, 0, 0, 0, - 0, 0, 0, 0,254,127,190, 67,254,127, 52,196, 0, 0, 0, 0,125, 1, 0, 0,142, 1, 0, 0, 0, 0, 0, 0,209, 2, 0, 0, - 0, 0, 0, 0,126, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0,209, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, - 18, 0, 0, 4, 6, 0,142, 1,210, 2,125, 1,210, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -241, 5, 0, 0,126, 7, 0, 0, 0, 0, 0, 0,209, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -142, 1,210, 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, 88,211,216, 3, 0, 0, 0, 0, -152, 50,217, 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, 68, 65, 84, 65, 88, 1, 0, 0, 88,211,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, - 56,213,216, 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, - 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, - 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, - 67,111,110,116,101,120,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,220,255,124, 1, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, - 56,213,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 24,215,216, 3, 0, 0, 0, 0, 88,211,216, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255,124, 1, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 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, 68, 65, 84, 65, 88, 1, 0, 0, 24,215,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, -248,216,216, 3, 0, 0, 0, 0, 56,213,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,255,124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, -248,216,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,216,218,216, 3, 0, 0, 0, 0, 24,215,216, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115, -105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115, -105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140,254,124, 1,203, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,216,218,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, -184,220,216, 3, 0, 0, 0, 0,248,216,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 65,110,116,105, 45, 65,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 58,254,124, 1, 58, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, -184,220,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,152,222,216, 3, 0, 0, 0, 0,216,218,216, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, - 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, - 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97,109,112,108,101,100, 32, 77,111,116,105,111,110, 32, 66, -108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,254,124, 1, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,152,222,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, -120,224,216, 3, 0, 0, 0, 0,184,220,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 83,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 10,254,124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, -120,224,216, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,248, 44,217, 3, 0, 0, 0, 0,152,222,216, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114, -109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114, -109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,242,253,124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,248, 44,217, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, -216, 46,217, 3, 0, 0, 0, 0,120,224,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80,111,115,116, 32, 80,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,218,253,124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, -216, 46,217, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,184, 48,217, 3, 0, 0, 0, 0,248, 44,217, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194,253,124, 1, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,184, 48,217, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, -152, 50,217, 3, 0, 0, 0, 0,216, 46,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, - 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, - 79,117,116,112,117,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, 40,253,124, 1,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, -152, 50,217, 3, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184, 48,217, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,253,124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,184,129,199, 3, 0, 0, 0, 0,179, 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, - 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, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -255, 21, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, - 88, 26,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,120, 27,215, 3, 0, 0, 0, 0, 56, 25,215, 3, 0, 0, 0, 0, - 40, 52,201, 3, 0, 0, 0, 0, 8, 54,201, 3, 0, 0, 0, 0,168, 49,201, 3, 0, 0, 0, 0,136, 51,201, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,249, 2, 0, 0,239, 5, 0, 0,105, 1, 0, 0,167, 3, 0, 0, 1, 1,247, 2, 63, 2, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 52,217, 3, 0, 0, 0, 0,120, 52,217, 3, 0, 0, 0, 0, -168,246,216, 3, 0, 0, 0, 0,104,253,216, 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, 68, 65, 84, 65, 40, 1, 0, 0,168,246,216, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 88,248,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,113, 68, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,192, 61, 68, 0, 0, 0, 0, 0, 0,208, 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,246, 2, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0,128, 61, 68, 0, 0,200, 65, 0,128, 61, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,247, 2, 26, 0,247, 2, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,249, 2, 0, 0,239, 5, 0, 0,105, 1, 0, 0,130, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,247, 2, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 88,248,216, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 8,250,216, 3, 0, 0, 0, 0,168,246,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, - 0, 64, 70,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67,255,127, 70,196, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, - 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, - 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, - 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0, 44, 3,143, 0, 26, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,249, 2, 0, 0,249, 2, 0, 0,131, 1, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 37, 2, 0, 0, 5, 0, 3, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8,250,216, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,184,251,216, 3, 0, 0, 0, 0, 88,248,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 67, - 0, 0,206,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, 0, 0,206,194, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, - 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, - 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, - 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,249, 2, 0, 0,239, 5, 0, 0,131, 1, 0, 0,131, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 6, 0, 34, 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, 68, 65, 84, 65, 40, 1, 0, 0,184,251,216, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0,104,253,216, 3, 0, 0, 0, 0, 8,250,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, - 0,128,142,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0, 0, 26,196, 0, 0, 0, 0,163, 0, 0, 0,180, 0, 0, 0, - 18, 0, 0, 0,121, 2, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, - 18, 0, 0, 0,121, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, - 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,180, 0,122, 2,163, 0,104, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,239, 5, 0, 0,239, 5, 0, 0,131, 1, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0,104,253,216, 3, 0, 0, 0, 0, -215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,251,216, 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,249, 2, 0, 0,239, 5, 0, 0,131, 1, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,247, 2, 37, 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,200, 76,217, 3, 0, 0, 0, 0, 68, 65, 84, 65,112, 3, 0, 0,200, 76,217, 3, 0, 0, 0, 0, -173, 0, 0, 0, 1, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74,141,193, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0, -225,215,163,188, 0, 0, 0, 0, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, - 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -214,211,111,193, 0, 0,128, 63, 69,239,209, 62, 70,119,105, 63,176, 84, 89,188, 0, 0, 0, 0, 53,177,205,190,142, 74, 70, 62, -166, 33,101, 63, 0, 0, 0, 0,185,158, 81, 63, 35, 44,185,190, 43, 61,228, 62, 0, 0, 0, 0,164, 96, 68, 65,111,121,173,192, -248,209,213, 64, 0, 0,128, 63,178,157,229, 62, 30,132, 27,191,222,160, 81,191,184,158, 81,191,117, 90,127, 63,166,235,149, 62, - 9, 46,185, 62, 35, 44,185, 62,145,180,109,188,212, 60,173, 63,129, 63,228,190, 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0, - 96,132,111, 65,214,211,111, 65,217,236,191, 62, 54,117, 85, 63,224,246, 70,188, 0,160, 32,182,252, 5,136,190, 43, 33, 3, 62, -235,135, 23, 63, 0, 0, 96, 53,215,104, 25,196,133,132,135, 67, 37, 9,167,195,136,252, 71,194, 3, 54, 25, 68,158, 87,135,195, -205,209,166, 67,151,254, 71, 66, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, - 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -214,211,111,193, 0, 0,128, 63,178,157,229, 62, 30,132, 27,191,222,160, 81,191,184,158, 81,191,117, 90,127, 63,166,235,149, 62, - 9, 46,185, 62, 35, 44,185, 62,145,180,109,188,212, 60,173, 63,129, 63,228,190, 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0, - 96,132,111, 65,214,211,111, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 46, 86, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 86, 45, 64, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 86, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, 3,236,234,190,214,211,111, 65,214,211,111, 65, - 0, 0, 0, 0, 0, 0, 0, 0,107,227, 29, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, -255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 30, 33, 12, 66, - 86,152,137, 66,116, 27,126, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 1, 0, 0, -120, 52,217, 3, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65,205,204, 76, 62, - 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200,213,217, 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, - 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, 8, 8,128, 0, 0, 0, 12, 66, 0, 0,128, 63, 10,215, 35, 60, - 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, - 10, 0, 7, 1, 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, 68, 65, 84, 65,160, 0, 0, 0,120, 27,215, 3, 0, 0, 0, 0, -214, 0, 0, 0, 1, 0, 0, 0,152, 28,215, 3, 0, 0, 0, 0, 88, 26,215, 3, 0, 0, 0, 0,232, 45,201, 3, 0, 0, 0, 0, -232, 50,201, 3, 0, 0, 0, 0,136, 51,201, 3, 0, 0, 0, 0, 72, 50,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,239, 5, 0, 0, 0, 0, 0, 0,103, 1, 0, 0, 18, 18,240, 5,104, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,184, 80,217, 3, 0, 0, 0, 0,184, 80,217, 3, 0, 0, 0, 0, 24,255,216, 3, 0, 0, 0, 0, -200, 0,217, 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, 68, 65, 84, 65, 40, 1, 0, 0, 24,255,216, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, -200, 0,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,160, 67, 0, 0, 0, 0, 0, 0,208, 65, - 0, 0, 0, 0, 0, 0,190, 68, 0, 0, 0, 0, 0, 0,208, 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,239, 5, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, - 0,224,189, 68, 0, 0,200, 65, 0,224,189, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, - 4, 0, 12, 0, 10, 0,240, 5, 26, 0,240, 5, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,239, 5, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 5, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,200, 0,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 24,255,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,189, 68, 0, 0, 0, 0, 0, 0, 51, 67, - 0, 0, 0, 0, 0,224,187, 68, 0, 0, 0, 0, 0, 0,167, 67,223, 5, 0, 0,240, 5, 0, 0, 0, 0, 0, 0, 77, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,222, 5, 0, 0, 0, 0, 0, 0, 77, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 2, 2, 0, 0, 1, 0, 3, 3, - 2, 0, 0, 4, 10, 0,240, 5, 78, 1,223, 5, 78, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,239, 5, 0, 0, 26, 0, 0, 0,103, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 5, 78, 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, 68, 65, 84, 65, 40, 0, 0, 0,136, 96,216, 3, 0, 0, 0, 0,193, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 40,182,117, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0, 40,182,117, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65,136, 1, 0, 0,184, 80,217, 3, 0, 0, 0, 0,194, 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, 18, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 96,216, 3, 0, 0, 0, 0,136, 96,216, 3, 0, 0, 0, 0, 62, 62, 62, 32, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112,121,116,104, -111,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 4, 0, 0, - 8, 4, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,152, 28,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,184, 29,215, 3, - 0, 0, 0, 0,120, 27,215, 3, 0, 0, 0, 0,200, 52,201, 3, 0, 0, 0, 0,168, 49,201, 3, 0, 0, 0, 0, 8, 49,201, 3, - 0, 0, 0, 0,104, 53,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 5, 0, 0,126, 7, 0, 0,237, 2, 0, 0, -167, 3, 0, 0, 3, 3,142, 1,187, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 4,209, 3, - 0, 0, 0, 0, 8, 4,209, 3, 0, 0, 0, 0,120, 2,217, 3, 0, 0, 0, 0, 40, 4,217, 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, 68, 65, 84, 65, - 40, 1, 0, 0,120, 2,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 40, 4,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,128,244, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,199, 67, 0, 0, 0, 0, - 0, 0,208, 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,141, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,198, 67, 0, 0,200, 65, 0,128,198, 67, - 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,142, 1, 26, 0,142, 1, - 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 5, 0, 0,126, 7, 0, 0,237, 2, 0, 0, - 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, - 40, 1, 0, 0, 40, 4,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 2,217, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0,128,141, 67, 0, 0,244,194, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,190, 67, 0, 0, 15,195, - 0, 0, 0, 0,125, 1, 0, 0,142, 1, 0, 0, 18, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0, - 17, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 18, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 18, 6, 0, 0, 2, 0, 3, 3, 0, 0, 12, 4, 6, 0,142, 1,161, 0,125, 1, -143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 5, 0, 0,126, 7, 0, 0, 7, 3, 0, 0, -167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 1,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 24, 1, 0, 0, 8, 4,209, 3, 0, 0, 0, 0,183, 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, 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,248, 11,217, 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, 1, 0, 0, 0, 68, 65, 84, 65, 16, 0, 0, 0,248, 11,217, 3, 0, 0, 0, 0,237, 0, 0, 0, - 1, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0,184, 33,199, 3, 0, 0, 0, 0, 68, 65, 84, 65,224, 0, 0, 0,184, 33,199, 3, - 0, 0, 0, 0,236, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 19, 0, 0, 0, - 1, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 20, 0, 0, 0, 1, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 21, 0, 1, 0, - 1, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 24, 51,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 0,184,219,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,136, 48,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 0,152, 7,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,216, 29,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 0,168,225,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,120,209,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 0,200,213,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 24, 98,200, 3, 0, 0, 0, 0, 21, 0, 0, 0, - 1, 0, 1, 0,168,194,217, 3, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,184, 29,215, 3, 0, 0, 0, 0,214, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 28,215, 3, 0, 0, 0, 0,232, 50,201, 3, 0, 0, 0, 0,104, 48,201, 3, - 0, 0, 0, 0, 8, 54,201, 3, 0, 0, 0, 0, 40, 52,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -247, 2, 0, 0,105, 1, 0, 0,167, 3, 0, 0, 9, 9,248, 2, 63, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,200,114,217, 3, 0, 0, 0, 0,200,114,217, 3, 0, 0, 0, 0,248, 82,217, 3, 0, 0, 0, 0,168, 84,217, 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, 68, 65, 84, 65, 40, 1, 0, 0,248, 82,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,168, 84,217, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, - 0, 0, 62, 68, 0, 0, 0, 0, 0, 0,208, 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,247, 2, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192, 61, 68, - 0, 0,200, 65, 0,192, 61, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, - 10, 0,248, 2, 26, 0,248, 2, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -247, 2, 0, 0,105, 1, 0, 0,130, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 2, 26, 0, - 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,168, 84,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,248, 82,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,189, 68, 0, 0, 0, 0, 0,192, 22, 68,248,150, 23, 68, - 8, 41,100, 68, 46,224, 62, 67,233, 15,206, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,247, 2, 0, 0, 0, 0, 0, 0, 36, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,215, 35, 60, 0, 0,122, 68, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 4, - 10, 0,248, 2, 37, 2,248, 2, 37, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -247, 2, 0, 0,131, 1, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 2, 37, 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, 68, 65, 84, 65,160, 2, 0, 0,200,114,217, 3, 0, 0, 0, 0,186, 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, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 32, 0, 0, 0, 0, 0, 0, 0, 12, 0, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -205,204,204, 61,231, 1, 0, 0,243, 1, 0, 0,122, 1, 0, 0,124, 1, 0, 0,231, 1, 0, 0,243, 1, 0, 0, 4, 0, 0, 0, -124, 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, 83, 78, 0, 0, - 8, 1, 0, 0,232,117,217, 3, 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0, 24,157,217, 3, 0, 0, 0, 0, 56, 43,217, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 85, 86, 32, 69,100,105,116,105,110,103, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 77, 0, 0, + 88, 1, 0, 0,152,208,194, 6, 0, 0, 0, 0,146, 1, 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, 87, 77, 87,105,110, 77, 97,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 54,201, 3, 0, 0, 0, 0, 8, 59,201, 3, 0, 0, 0, 0, 56, 97,216, 3, - 0, 0, 0, 0, 24,104,216, 3, 0, 0, 0, 0,216, 30,215, 3, 0, 0, 0, 0, 24, 33,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,210,194, 6, 0, 0, 0, 0, 56,210,194, 6, 0, 0, 0, 0, 56,210,194, 6, + 0, 0, 0, 0, 56,210,194, 6, 0, 0, 0, 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, 16, 0, 0, 0, 2, 0, 0, 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, 88, 23, 3, 0, 73,127, 0, 0, 56, 25, 3, 0, 73,127, 0, 0, 88, 23, 3, 0, + 73,127, 0, 0, 72, 24, 3, 0, 73,127, 0, 0, 56, 25, 3, 0, 73,127, 0, 0, 40, 26, 3, 0, 73,127, 0, 0, 40, 26, 3, 0, + 73,127, 0, 0, 40, 26, 3, 0, 73,127, 0, 0, 68, 65, 84, 65, 0, 1, 0, 0, 56,210,194, 6, 0, 0, 0, 0,147, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,188, 2, 0, 73,127, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0,248,163,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115, 99,114,101,101,110, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 6, 1, 0,126, 7,146, 4, 0, 0, 0, 0, + 1, 0,238, 3, 0, 0, 0, 0, 1, 0, 0, 0,200,225, 12, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,184, 35, 13, 0, 73,127, 0, 0, 8, 93,223, 0, 73,127, 0, 0, 8, 93,223, 0, + 73,127, 0, 0, 8,228, 12, 0, 73,127, 0, 0,120,203, 12, 0, 73,127, 0, 0, 56,213,226, 0, 73,127, 0, 0,136,226, 12, 0, + 73,127, 0, 0, 24, 41, 13, 0, 73,127, 0, 0, 8,237,224, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 78, 0, 0, 8, 1, 0, 0,136,211,194, 6, 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0,120, 55,195, 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, 83, 82, 65,110, +105,109, 97,116,105,111,110, 0, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,154,194, 6, 0, 0, 0, 0,104,219,194, 6, + 0, 0, 0, 0,216,219,194, 6, 0, 0, 0, 0, 24,232,194, 6, 0, 0, 0, 0,136,232,194, 6, 0, 0, 0, 0,168, 45,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 32, 0, 0, 0,184,154,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40,155,194, 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, 68, 65, 84, 65, - 32, 0, 0, 0,168, 54,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 55,201, 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, 68, 65, 84, 65, 32, 0, 0, 0, 72, 55,201, 3, - 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232, 55,201, 3, 0, 0, 0, 0,168, 54,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,232, 55,201, 3, 0, 0, 0, 0,211, 0, 0, 0, - 1, 0, 0, 0,136, 56,201, 3, 0, 0, 0, 0, 72, 55,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 5, 4, - 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,136, 56,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40, 57,201, 3, - 0, 0, 0, 0,232, 55,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 32, 0, 0, 0, 40, 57,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200, 57,201, 3, 0, 0, 0, 0,136, 56,201, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,200, 57,201, 3, - 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104, 58,201, 3, 0, 0, 0, 0, 40, 57,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,126, 7,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,104, 58,201, 3, 0, 0, 0, 0,211, 0, 0, 0, - 1, 0, 0, 0, 8, 59,201, 3, 0, 0, 0, 0,200, 57,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 3,234, 3, - 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8, 59,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,104, 58,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 3, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0, 56, 97,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232, 97,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 72, 55,201, 3, 0, 0, 0, 0,232, 55,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0,232, 97,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152, 98,216, 3, 0, 0, 0, 0, 56, 97,216, 3, - 0, 0, 0, 0, 72, 55,201, 3, 0, 0, 0, 0, 40, 57,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0,152, 98,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72, 99,216, 3, 0, 0, 0, 0,232, 97,216, 3, - 0, 0, 0, 0,232, 55,201, 3, 0, 0, 0, 0,200, 57,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0, 72, 99,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248, 99,216, 3, 0, 0, 0, 0,152, 98,216, 3, - 0, 0, 0, 0, 40, 57,201, 3, 0, 0, 0, 0,200, 57,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0,248, 99,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168,100,216, 3, 0, 0, 0, 0, 72, 99,216, 3, - 0, 0, 0, 0, 40, 57,201, 3, 0, 0, 0, 0,104, 58,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0,168,100,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88,101,216, 3, 0, 0, 0, 0,248, 99,216, 3, - 0, 0, 0, 0,168, 54,201, 3, 0, 0, 0, 0, 8, 59,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0, 88,101,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8,102,216, 3, 0, 0, 0, 0,168,100,216, 3, - 0, 0, 0, 0,168, 54,201, 3, 0, 0, 0, 0, 40, 57,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0, 8,102,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184,102,216, 3, 0, 0, 0, 0, 88,101,216, 3, - 0, 0, 0, 0,104, 58,201, 3, 0, 0, 0, 0, 8, 59,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0,184,102,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104,103,216, 3, 0, 0, 0, 0, 8,102,216, 3, - 0, 0, 0, 0,200, 57,201, 3, 0, 0, 0, 0,104, 58,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0,104,103,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24,104,216, 3, 0, 0, 0, 0,184,102,216, 3, - 0, 0, 0, 0,136, 56,201, 3, 0, 0, 0, 0, 8, 59,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0, 24,104,216, 3, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,103,216, 3, - 0, 0, 0, 0,136, 56,201, 3, 0, 0, 0, 0,200, 57,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, -160, 0, 0, 0,216, 30,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,248, 31,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 40, 57,201, 3, 0, 0, 0, 0, 72, 55,201, 3, 0, 0, 0, 0,232, 55,201, 3, 0, 0, 0, 0,200, 57,201, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,235, 3, 0, 0, 5, 4, 0, 0, 7, 7,127, 7, - 27, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,201,207, 3, 0, 0, 0, 0, 88,201,207, 3, - 0, 0, 0, 0, 88, 86,217, 3, 0, 0, 0, 0, 8, 88,217, 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, 68, 65, 84, 65, 40, 1, 0, 0, 88, 86,217, 3, - 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 8, 88,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32,148, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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, -126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,235, 3, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8, 88,217, 3, - 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 86,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0,240,109, 69, 0, 0,128,192, 0, 0, 0, 0, 0, 0, 0, 0,255,255,109, 69, 0, 0, 0,192, 0, 0, 0, 0,112, 7, 0, 0, -129, 7, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, -111, 7, 0, 0, 18, 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,128, 63, - 0, 0,128, 63, 2, 0, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,129, 7, 2, 0,112, 7, 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, 5, 4, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65,160, 0, 0, 0,248, 31,215, 3, - 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 24, 33,215, 3, 0, 0, 0, 0,216, 30,215, 3, 0, 0, 0, 0,168, 54,201, 3, - 0, 0, 0, 0, 40, 57,201, 3, 0, 0, 0, 0,104, 58,201, 3, 0, 0, 0, 0, 8, 59,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,199, 3, 0, 0, 0, 0, 0, 0,233, 3, 0, 0, 6, 6,200, 3,234, 3, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,119,217, 3, 0, 0, 0, 0,120,119,217, 3, 0, 0, 0, 0,184, 89,217, 3, - 0, 0, 0, 0, 24, 93,217, 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, 68, 65, 84, 65, 40, 1, 0, 0,184, 89,217, 3, 0, 0, 0, 0,215, 0, 0, 0, - 1, 0, 0, 0,104, 91,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,215, 67, 0, 0, 0, 0, - 0, 0,208, 65, 0, 0, 0, 0, 0, 0,114, 68, 0, 0, 0, 0, 0, 0,208, 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,199, 3, 0, 0, 0, 0, 0, 0, - 25, 0, 0, 0, 0,192,113, 68, 0, 0,200, 65, 0,192,113, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,200, 3, 26, 0,200, 3, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,199, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,200, 3, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,104, 91,217, 3, 0, 0, 0, 0,215, 0, 0, 0, - 1, 0, 0, 0, 24, 93,217, 3, 0, 0, 0, 0,184, 89,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 67, 0,192,115,196, - 0, 0, 0, 0, 0, 0, 0, 0,254,255, 74, 67,254,255,115,196, 0, 0, 0, 0,203, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0, -207, 3, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, -207, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, - 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,220, 0,208, 3,203, 0,208, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,219, 0, 0, 0, 26, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,220, 0,208, 3, 0, 0, 4, 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, 88, 54,217, 3, - 0, 0, 0, 0, 88, 54,217, 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, 68, 65, 84, 65, 88, 1, 0, 0, 88, 54,217, 3, 0, 0, 0, 0,213, 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, 73, 77, 65, 71, 69, 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 73, 77, 65, 71, 69, 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 71,114,101, 97,115,101, 32, 80,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,152,255,202, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 1, 0, 0, 24, 93,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 91,217, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 67, 51, 51, 43,191,154,153,213, 63, 51, 51,131,191, -154,153, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,236, 2, 0, 0, 0, 0, 0, 0,208, 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,220, 0, 0, 0,199, 3, 0, 0, 26, 0, 0, 0, -233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,236, 2,208, 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, 68, 65, 84, 65, - 40, 33, 0, 0,120,119,217, 3, 0, 0, 0, 0,184, 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, 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,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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,240, 65, 0, 0, 0, 0,154,153,153, 62, 0, 0, 0, 0,100, 0, 0, 0,154,153,153, 62,100, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,160, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, -160, 0, 0, 0, 24, 33,215, 3, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 31,215, 3, - 0, 0, 0, 0, 8, 59,201, 3, 0, 0, 0, 0,104, 58,201, 3, 0, 0, 0, 0,200, 57,201, 3, 0, 0, 0, 0,136, 56,201, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,201, 3, 0, 0,126, 7, 0, 0, 0, 0, 0, 0,233, 3, 0, 0, 1, 1,182, 3, -234, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 59,217, 3, 0, 0, 0, 0,248, 59,217, 3, - 0, 0, 0, 0,200, 94,217, 3, 0, 0, 0, 0,136,101,217, 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, 68, 65, 84, 65, 40, 1, 0, 0,200, 94,217, 3, - 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,120, 96,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 64,113, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,128,109, 68, 0, 0, 0, 0, 0, 0,208, 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, -181, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 64,109, 68, 0, 0,200, 65, 0, 64,109, 68, 0, 0,200, 65, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,182, 3, 26, 0,182, 3, 26, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,201, 3, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,182, 3, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,120, 96,217, 3, - 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 40, 98,217, 3, 0, 0, 0, 0,200, 94,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32, 67, 0, 0, 86,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 0, 86,196, 0, 0, 0, 0,143, 0, 0, 0, -160, 0, 0, 0, 0, 0, 0, 0, 87, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, -142, 0, 0, 0, 0, 0, 0, 0, 87, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, - 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0, 88, 3,143, 0, 88, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,201, 3, 0, 0,104, 4, 0, 0,146, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 88, 3, 0, 0, 5, 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, 56, 56,217, 3, 0, 0, 0, 0, 56, 56,217, 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, 68, 65, 84, 65, 88, 1, 0, 0, 56, 56,217, 3, - 0, 0, 0, 0,213, 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, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, - 99,116,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, - 99,116,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 98,106,101, 99,116, 32, 84,111,111,108,115, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,233,253,143, 0,255, 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, 68, 65, 84, 65, 40, 1, 0, 0, 40, 98,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216, 99,217, 3, - 0, 0, 0, 0,120, 96,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 67, 0, 0,242,194, 0, 0, 0, 0, 0, 0, 0, 0, -231,102, 16, 67, 91, 90,242,194, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, -142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, - 6, 0,160, 0,120, 0,143, 0,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,201, 3, 0, 0, -104, 4, 0, 0, 26, 0, 0, 0,145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0,120, 0, - 0, 0, 6, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 58,217, 3, 0, 0, 0, 0, 24, 58,217, 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, 68, 65, 84, 65, 88, 1, 0, 0, 24, 58,217, 3, 0, 0, 0, 0,213, 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, 86, 73, 69, 87, - 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, - 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79,112,101,114, - 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,255, -144, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,216, 99,217, 3, - 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,136,101,217, 3, 0, 0, 0, 0, 40, 98,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 35, 67, 0,128,126,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67,255,191,126,196, 0, 0, 0, 0,163, 0, 0, 0, -180, 0, 0, 0, 18, 0, 0, 0, 12, 4, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, -162, 0, 0, 0, 18, 0, 0, 0, 12, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, - 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,180, 0, 13, 4,163, 0,251, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,126, 7, 0, 0, 26, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0,136,101,217, 3, - 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 99,217, 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,105, 4, 0, 0,126, 7, 0, 0, 26, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 3,208, 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, 40,153,217, 3, 0, 0, 0, 0, 68, 65, 84, 65,112, 3, 0, 0, 40,153,217, 3, - 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0, 72,246,172, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 13,128,191, 0, 0,128,191, 0, 0, 0, 0, - 0, 0, 0, 0, 74,215, 76,190, 0, 0, 0, 0, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63, -143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 25, 95,192, 0, 0,128, 63, 69,239,209, 62, 70,119,105, 63,160, 84, 89,188, 0, 0, 0, 0, 52,177,205,190, -142, 74, 70, 62,166, 33,101, 63, 0, 0, 0, 0,185,158, 81, 63, 35, 44,185,190, 43, 61,228, 62, 0, 0, 0, 0,188,173, 54, 64, -136, 95,161,191,147,231,198, 63, 0, 0,128, 63,185,214, 13, 63,208,249,224,190, 48,180, 81,191,184,158, 81,191,189,188,157, 63, -140,225, 88, 62, 26, 63,185, 62, 35, 44,185, 62,241,213,146,188,206,156,122, 63,138, 84,228,190, 42, 61,228,190, 0, 0, 0, 0, - 0, 0, 0, 0,100, 98, 82, 64, 0, 25, 95, 64,121, 92,155, 62,151,198, 44, 63,192,214, 32,188, 0, 0, 40,180,195, 15,188,190, -132, 75, 53, 62,216,125, 81, 63, 0, 0,192,179,115, 77,100,193, 17,173,201, 64,181,148,248,192,203,247,159,192,233, 74, 87, 65, -247, 46,190,192, 88,106,234, 64, 45, 8,160, 64, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63, -143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 25, 95,192, 0, 0,128, 63,185,214, 13, 63,208,249,224,190, 48,180, 81,191,184,158, 81,191,189,188,157, 63, -140,225, 88, 62, 26, 63,185, 62, 35, 44,185, 62,241,213,146,188,206,156,122, 63,138, 84,228,190, 42, 61,228,190, 0, 0, 0, 0, - 0, 0, 0, 0,100, 98, 82, 64, 0, 25, 95, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,201,250, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -248,201,250, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,201,250, 62, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, 3,236,234,190, 0, 25, 95, 64, - 0, 25, 95, 64, 0, 0, 0, 0, 0, 0, 0, 0,114,145,245, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 30, 33, 12, 66, 85,152,137, 66,116, 27,126, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 96, 1, 0, 0,248, 59,217, 3, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, -205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200,213,217, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, 8, 8,128, 0, 0, 0, 12, 66, 0, 0,128, 63, -205,204,204, 61, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 16, 0, 10, 0, 7, 1, 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, 83, 78, 0, 0, 8, 1, 0, 0, 24,157,217, 3, - 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,117,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 86,105,100,101,111, 32, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,168, 59,201, 3, 0, 0, 0, 0,136, 66,201, 3, 0, 0, 0, 0,200,104,216, 3, 0, 0, 0, 0,120,116,216, 3, - 0, 0, 0, 0, 56, 34,215, 3, 0, 0, 0, 0,184, 38,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,168,194,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 32, 0, 0, 0,168, 59,201, 3, - 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 60,201, 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, 68, 65, 84, 65, 32, 0, 0, 0, 72, 60,201, 3, 0, 0, 0, 0,211, 0, 0, 0, - 1, 0, 0, 0,232, 60,201, 3, 0, 0, 0, 0,168, 59,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,222, 2, - 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,232, 60,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136, 61,201, 3, - 0, 0, 0, 0, 72, 60,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4,222, 2, 0, 0, 0, 0, 68, 65, 84, 65, - 32, 0, 0, 0,136, 61,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40, 62,201, 3, 0, 0, 0, 0,232, 60,201, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 40, 62,201, 3, - 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200, 62,201, 3, 0, 0, 0, 0,136, 61,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,200, 62,201, 3, 0, 0, 0, 0,211, 0, 0, 0, - 1, 0, 0, 0,104, 63,201, 3, 0, 0, 0, 0, 40, 62,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4,195, 2, - 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,104, 63,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8, 64,201, 3, - 0, 0, 0, 0,200, 62,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 92, 1, 0, 0, 0, 0, 68, 65, 84, 65, - 32, 0, 0, 0, 8, 64,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,168, 64,201, 3, 0, 0, 0, 0,104, 63,201, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,168, 64,201, 3, - 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 65,201, 3, 0, 0, 0, 0, 8, 64,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 48, 2,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 72, 65,201, 3, 0, 0, 0, 0,211, 0, 0, 0, - 1, 0, 0, 0,232, 65,201, 3, 0, 0, 0, 0,168, 64,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 1, - 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,232, 65,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136, 66,201, 3, - 0, 0, 0, 0, 72, 65,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 2, 92, 1, 0, 0, 0, 0, 68, 65, 84, 65, - 32, 0, 0, 0,136, 66,201, 3, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232, 65,201, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 68, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,104,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120,105,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 60,201, 3, - 0, 0, 0, 0,232, 60,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120,105,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40,106,216, 3, 0, 0, 0, 0,200,104,216, 3, 0, 0, 0, 0, 72, 60,201, 3, - 0, 0, 0, 0, 40, 62,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,106,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216,106,216, 3, 0, 0, 0, 0,120,105,216, 3, 0, 0, 0, 0,232, 60,201, 3, - 0, 0, 0, 0,200, 62,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,106,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136,107,216, 3, 0, 0, 0, 0, 40,106,216, 3, 0, 0, 0, 0, 40, 62,201, 3, - 0, 0, 0, 0,200, 62,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136,107,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56,108,216, 3, 0, 0, 0, 0,216,106,216, 3, 0, 0, 0, 0,200, 62,201, 3, - 0, 0, 0, 0,104, 63,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,108,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232,108,216, 3, 0, 0, 0, 0,136,107,216, 3, 0, 0, 0, 0,168, 59,201, 3, - 0, 0, 0, 0, 8, 64,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232,108,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152,109,216, 3, 0, 0, 0, 0, 56,108,216, 3, 0, 0, 0, 0, 40, 62,201, 3, - 0, 0, 0, 0,168, 64,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,152,109,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72,110,216, 3, 0, 0, 0, 0,232,108,216, 3, 0, 0, 0, 0, 8, 64,201, 3, - 0, 0, 0, 0, 72, 65,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72,110,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248,110,216, 3, 0, 0, 0, 0,152,109,216, 3, 0, 0, 0, 0, 72, 65,201, 3, - 0, 0, 0, 0,232, 65,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248,110,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168,111,216, 3, 0, 0, 0, 0, 72,110,216, 3, 0, 0, 0, 0,168, 64,201, 3, - 0, 0, 0, 0,232, 65,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168,111,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88,112,216, 3, 0, 0, 0, 0,248,110,216, 3, 0, 0, 0, 0,104, 63,201, 3, - 0, 0, 0, 0,136, 66,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88,112,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8,113,216, 3, 0, 0, 0, 0,168,111,216, 3, 0, 0, 0, 0,136, 61,201, 3, - 0, 0, 0, 0,136, 66,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8,113,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184,113,216, 3, 0, 0, 0, 0, 88,112,216, 3, 0, 0, 0, 0, 8, 64,201, 3, - 0, 0, 0, 0,136, 66,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184,113,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104,114,216, 3, 0, 0, 0, 0, 8,113,216, 3, 0, 0, 0, 0,168, 59,201, 3, - 0, 0, 0, 0,136, 61,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104,114,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24,115,216, 3, 0, 0, 0, 0,184,113,216, 3, 0, 0, 0, 0,200, 62,201, 3, - 0, 0, 0, 0,168, 64,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24,115,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200,115,216, 3, 0, 0, 0, 0,104,114,216, 3, 0, 0, 0, 0,104, 63,201, 3, - 0, 0, 0, 0,232, 65,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,115,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120,116,216, 3, 0, 0, 0, 0, 24,115,216, 3, 0, 0, 0, 0, 40, 62,201, 3, - 0, 0, 0, 0, 72, 65,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120,116,216, 3, - 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,115,216, 3, 0, 0, 0, 0,104, 63,201, 3, - 0, 0, 0, 0, 72, 65,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 56, 34,215, 3, - 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 88, 35,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 62,201, 3, - 0, 0, 0, 0, 72, 60,201, 3, 0, 0, 0, 0,232, 60,201, 3, 0, 0, 0, 0,200, 62,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 0, 0, 0, 40,155,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,216,212,194, 6, 0, 0, 0, 0,184,154,194, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,222, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,216,212,194, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72,213,194, 6, 0, 0, 0, 0, 40,155,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,240, 4,222, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 72,213,194, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,184,213,194, 6, 0, 0, 0, 0,216,212,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,184,213,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40,214,194, 6, + 0, 0, 0, 0, 72,213,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0, 40,214,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,152,214,194, 6, 0, 0, 0, 0,184,213,194, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,152,214,194, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8,215,194, 6, 0, 0, 0, 0, 40,214,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 4, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8,215,194, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,120,215,194, 6, 0, 0, 0, 0,152,214,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 4,195, 2, + 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,120,215,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232,215,194, 6, + 0, 0, 0, 0, 8,215,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 60, 1, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,232,215,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 88,216,194, 6, 0, 0, 0, 0,120,215,194, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 60, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 88,216,194, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200,216,194, 6, 0, 0, 0, 0,232,215,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,200,216,194, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0, 56,217,194, 6, 0, 0, 0, 0, 88,216,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 88, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 56,217,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,168,217,194, 6, + 0, 0, 0, 0,200,216,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 1, 88, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,168,217,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 24,218,194, 6, 0, 0, 0, 0, 56,217,194, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 1,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 24,218,194, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136,218,194, 6, 0, 0, 0, 0,168,217,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,136,218,194, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,248,218,194, 6, 0, 0, 0, 0, 24,218,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 1, 4, 1, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,248,218,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104,219,194, 6, + 0, 0, 0, 0,136,218,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 60, 2, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,104,219,194, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,218,194, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 60, 2, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,219,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72,220,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,155,194, 6, + 0, 0, 0, 0,216,212,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72,220,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184,220,194, 6, 0, 0, 0, 0,216,219,194, 6, 0, 0, 0, 0, 40,155,194, 6, + 0, 0, 0, 0,184,213,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184,220,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40,221,194, 6, 0, 0, 0, 0, 72,220,194, 6, 0, 0, 0, 0,216,212,194, 6, + 0, 0, 0, 0, 40,214,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,221,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152,221,194, 6, 0, 0, 0, 0,184,220,194, 6, 0, 0, 0, 0,184,213,194, 6, + 0, 0, 0, 0, 40,214,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,152,221,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8,222,194, 6, 0, 0, 0, 0, 40,221,194, 6, 0, 0, 0, 0,184,154,194, 6, + 0, 0, 0, 0,152,214,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8,222,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120,222,194, 6, 0, 0, 0, 0,152,221,194, 6, 0, 0, 0, 0, 72,213,194, 6, + 0, 0, 0, 0,152,214,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120,222,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232,222,194, 6, 0, 0, 0, 0, 8,222,194, 6, 0, 0, 0, 0, 40,214,194, 6, + 0, 0, 0, 0, 8,215,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232,222,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88,223,194, 6, 0, 0, 0, 0,120,222,194, 6, 0, 0, 0, 0,152,214,194, 6, + 0, 0, 0, 0,120,215,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88,223,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200,223,194, 6, 0, 0, 0, 0,232,222,194, 6, 0, 0, 0, 0, 72,213,194, 6, + 0, 0, 0, 0,232,215,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,223,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56,224,194, 6, 0, 0, 0, 0, 88,223,194, 6, 0, 0, 0, 0,120,215,194, 6, + 0, 0, 0, 0,232,215,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,224,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168,224,194, 6, 0, 0, 0, 0,200,223,194, 6, 0, 0, 0, 0,184,154,194, 6, + 0, 0, 0, 0, 88,216,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168,224,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24,225,194, 6, 0, 0, 0, 0, 56,224,194, 6, 0, 0, 0, 0, 8,215,194, 6, + 0, 0, 0, 0,200,216,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24,225,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136,225,194, 6, 0, 0, 0, 0,168,224,194, 6, 0, 0, 0, 0,152,214,194, 6, + 0, 0, 0, 0,200,216,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136,225,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248,225,194, 6, 0, 0, 0, 0, 24,225,194, 6, 0, 0, 0, 0, 88,216,194, 6, + 0, 0, 0, 0,200,216,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248,225,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104,226,194, 6, 0, 0, 0, 0,136,225,194, 6, 0, 0, 0, 0, 88,216,194, 6, + 0, 0, 0, 0, 56,217,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104,226,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216,226,194, 6, 0, 0, 0, 0,248,225,194, 6, 0, 0, 0, 0,200,216,194, 6, + 0, 0, 0, 0, 56,217,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,226,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72,227,194, 6, 0, 0, 0, 0,104,226,194, 6, 0, 0, 0, 0,184,213,194, 6, + 0, 0, 0, 0,168,217,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72,227,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184,227,194, 6, 0, 0, 0, 0,216,226,194, 6, 0, 0, 0, 0, 8,215,194, 6, + 0, 0, 0, 0,168,217,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184,227,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40,228,194, 6, 0, 0, 0, 0, 72,227,194, 6, 0, 0, 0, 0, 56,217,194, 6, + 0, 0, 0, 0,168,217,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,228,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152,228,194, 6, 0, 0, 0, 0,184,227,194, 6, 0, 0, 0, 0, 88,216,194, 6, + 0, 0, 0, 0, 24,218,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,152,228,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8,229,194, 6, 0, 0, 0, 0, 40,228,194, 6, 0, 0, 0, 0, 56,217,194, 6, + 0, 0, 0, 0,136,218,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8,229,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120,229,194, 6, 0, 0, 0, 0,152,228,194, 6, 0, 0, 0, 0, 24,218,194, 6, + 0, 0, 0, 0,136,218,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120,229,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232,229,194, 6, 0, 0, 0, 0, 8,229,194, 6, 0, 0, 0, 0,120,215,194, 6, + 0, 0, 0, 0,248,218,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232,229,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88,230,194, 6, 0, 0, 0, 0,120,229,194, 6, 0, 0, 0, 0, 8,215,194, 6, + 0, 0, 0, 0,248,218,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88,230,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200,230,194, 6, 0, 0, 0, 0,232,229,194, 6, 0, 0, 0, 0, 40,214,194, 6, + 0, 0, 0, 0,104,219,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,230,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56,231,194, 6, 0, 0, 0, 0, 88,230,194, 6, 0, 0, 0, 0,232,215,194, 6, + 0, 0, 0, 0,104,219,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,231,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168,231,194, 6, 0, 0, 0, 0,200,230,194, 6, 0, 0, 0, 0,248,218,194, 6, + 0, 0, 0, 0,104,219,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168,231,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24,232,194, 6, 0, 0, 0, 0, 56,231,194, 6, 0, 0, 0, 0,184,213,194, 6, + 0, 0, 0, 0, 24,218,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24,232,194, 6, + 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,231,194, 6, 0, 0, 0, 0,168,217,194, 6, + 0, 0, 0, 0,136,218,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,136,232,194, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 88,236,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,213,194, 6, + 0, 0, 0, 0, 40,155,194, 6, 0, 0, 0, 0,216,212,194, 6, 0, 0, 0, 0, 40,214,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0,196, 2, 0, 0,222, 2, 0, 0, 7, 7,241, 4, 27, 0, 1, 0, 0, 0, 0, 0, - 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,202,207, 3, 0, 0, 0, 0, 24,202,207, 3, 0, 0, 0, 0, 56,103,217, 3, - 0, 0, 0, 0,232,104,217, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56,103,217, 3, 0, 0, 0, 0,215, 0, 0, 0, - 1, 0, 0, 0,232,104,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,148, 68, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232, 54,195, 6, 0, 0, 0, 0,232, 54,195, 6, 0, 0, 0, 0,120,233,194, 6, + 0, 0, 0, 0,232,234,194, 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, 68, 65, 84, 65, 40, 1, 0, 0,120,233,194, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,232,234,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,148, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 32,158, 68, 0, 0, 0, 0, 0, 0,208, 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,240, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0,158, 68, 0, 0,200, 65, 0, 0,158, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, @@ -5142,8 +173,8 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0,241, 4, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,232,104,217, 3, 0, 0, 0, 0,215, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,103,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,109, 69, 0, 0,128,192, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,232,234,194, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,233,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,109, 69, 0, 0,128,192, 0, 0, 0, 0, 0, 0, 0, 0,255,255,109, 69, 0, 0, 0,192, 0, 0, 0, 0,112, 7, 0, 0,129, 7, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 18, 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,128, 63, 0, 0,128, 63, 2, 0, 0, 0, @@ -5152,737 +183,6242 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65,160, 0, 0, 0, 88, 35,215, 3, 0, 0, 0, 0,214, 0, 0, 0, - 1, 0, 0, 0,120, 36,215, 3, 0, 0, 0, 0, 56, 34,215, 3, 0, 0, 0, 0,168, 59,201, 3, 0, 0, 0, 0, 8, 64,201, 3, - 0, 0, 0, 0,136, 66,201, 3, 0, 0, 0, 0,136, 61,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 4, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 15, 15,241, 4, 68, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,200, 96,200, 3, 0, 0, 0, 0,200, 96,200, 3, 0, 0, 0, 0,152,106,217, 3, 0, 0, 0, 0, 72,108,217, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 88,236,194, 6, 0, 0, 0, 0,214, 0, 0, 0, + 1, 0, 0, 0,232, 4,195, 6, 0, 0, 0, 0,136,232,194, 6, 0, 0, 0, 0,152,214,194, 6, 0, 0, 0, 0,120,215,194, 6, + 0, 0, 0, 0,232,215,194, 6, 0, 0, 0, 0, 72,213,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 4, 0, 0, +240, 4, 0, 0, 0, 0, 0, 0, 59, 1, 0, 0, 4, 4,216, 0, 60, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,168, 3,195, 6, 0, 0, 0, 0,168, 3,195, 6, 0, 0, 0, 0, 72,237,194, 6, 0, 0, 0, 0,184,238,194, 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, 68, 65, 84, 65, 40, 1, 0, 0,152,106,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 72,108,217, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,140, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, - 0, 32,158, 68, 0, 0, 0, 0, 0, 0,208, 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,240, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0,158, 68, - 0, 0,200, 65, 0, 0,158, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, - 10, 0,241, 4, 26, 0,241, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 4, 26, 0, - 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72,237,194, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,184,238,194, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148, 67, 0, 0, 0, 0, 0, 0,208, 65, 98, 39, 38, 54, + 0, 0, 88, 67, 0, 0, 0, 0, 0, 0,208, 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,215, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 87, 67, + 0, 0,200, 65, 0, 0, 87, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, + 10, 0,216, 0, 26, 0,216, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 4, 0, 0, +240, 4, 0, 0, 34, 1, 0, 0, 59, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 0, 26, 0, + 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72,108,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,152,106,217, 3, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 72, 66,112,189, 17,192, -246, 70,125, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 4, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, 18, 0, 0, 0, 41, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,184,238,194, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 72,237,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 67, 0, 0, 61,196, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 71, 67, 1, 0,145,195, 0, 0, 0, 0,199, 0, 0, 0,216, 0, 0, 0, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 0, 0, + 62, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,198, 0, 0, 0, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, + 6, 0,216, 0, 34, 1,199, 0, 34, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 4, 0, 0, +240, 4, 0, 0, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 0, 34, 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, 40,240,194, 6, 0, 0, 0, 0, 8, 2,195, 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, 68, 65, 84, 65, 88, 1, 0, 0, 40,240,194, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,200,241,194, 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, 66, 85, 84, 84, + 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, 66, 85, 84, 84, + 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, 67,111,110,116, +101,120,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,220,255, +199, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,200,241,194, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,104,243,194, 6, 0, 0, 0, 0, 40,240,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255,199, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,104,243,194, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 8,245,194, 6, + 0, 0, 0, 0,200,241,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,121,101, +114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 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,255, +199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 8,245,194, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,168,246,194, 6, 0, 0, 0, 0,104,243,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140,254,199, 0,203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,168,246,194, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 72,248,194, 6, + 0, 0, 0, 0, 8,245,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,110,116,105, + 45, 65,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58,254, +199, 0, 58, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 72,248,194, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,232,249,194, 6, 0, 0, 0, 0,168,246,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117, +114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117, +114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97,109,112,108,101,100, 32, 77,111,116,105,111,110, 32, 66,108,117,114, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,254,199, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,232,249,194, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,136,251,194, 6, + 0, 0, 0, 0, 72,248,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,104, 97,100, +105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,254, +199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,136,251,194, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 40,253,194, 6, 0, 0, 0, 0,232,249,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99, +101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99, +101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,242,253,199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 40,253,194, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,200,254,194, 6, + 0, 0, 0, 0,136,251,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,111,115,116, + 32, 80,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,218,253, +199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,200,254,194, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,104, 0,195, 6, 0, 0, 0, 0, 40,253,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194,253,199, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,104, 0,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 8, 2,195, 6, + 0, 0, 0, 0,200,254,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, 79,117,116,112, +117,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, 40,253, +199, 0,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 8, 2,195, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,253,199, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,168, 3,195, 6, 0, 0, 0, 0,179, 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, 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, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 21, 0, 0, +160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,232, 4,195, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,216, 9,195, 6, 0, 0, 0, 0, 88,236,194, 6, 0, 0, 0, 0,184,154,194, 6, + 0, 0, 0, 0, 88,216,194, 6, 0, 0, 0, 0,200,216,194, 6, 0, 0, 0, 0,152,214,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 15, 15, 24, 4, 88, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184, 8,195, 6, 0, 0, 0, 0,184, 8,195, 6, 0, 0, 0, 0,216, 5,195, 6, + 0, 0, 0, 0, 72, 7,195, 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, 68, 65, 84, 65, 40, 1, 0, 0,216, 5,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 72, 7,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,140, 68, 0, 0, 0, 0, + 0, 0,208, 65, 39,182,158, 55, 0, 0,131, 68, 0, 0, 0, 0, 0, 0,208, 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, 23, 4, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,224,130, 68, 0, 0,200, 65, 0,224,130, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 24, 4, 26, 0, 24, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 4, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72, 7,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 5,195, 6, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, + 0, 0, 72, 66,112,189, 17,192,246, 70,125, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 18, 0, 0, 0, + 61, 0, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, 72, 0, 0, 0, + 0, 0, 0, 2, 4, 0, 0, 4, 8, 0, 24, 4, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 26, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 4, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,208, 0, 0, 0,184, 8,195, 6, 0, 0, 0, 0,190, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,216, 9,195, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,152, 16,195, 6, 0, 0, 0, 0,232, 4,195, 6, 0, 0, 0, 0,120,215,194, 6, + 0, 0, 0, 0,248,218,194, 6, 0, 0, 0, 0,104,219,194, 6, 0, 0, 0, 0,232,215,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 61, 1, 0, 0, 59, 2, 0, 0, 3, 3,216, 0,255, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 13,195, 6, 0, 0, 0, 0,168, 13,195, 6, 0, 0, 0, 0,200, 10,195, 6, + 0, 0, 0, 0, 56, 12,195, 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, 68, 65, 84, 65, 40, 1, 0, 0,200, 10,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 56, 12,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,244, 67, 0, 0, 0, 0, + 0, 0,208, 65, 98, 39, 38, 54, 0, 0, 88, 67, 0, 0, 0, 0, 0, 0,208, 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,215, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0, 0, 87, 67, 0, 0,200, 65, 0, 0, 87, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,216, 0, 26, 0,216, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 34, 2, 0, 0, 59, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,216, 0, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56, 12,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 10,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,141, 67, 0, 0,244,194, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 67, 0, 0, 83,195, 0, 0, 0, 0,199, 0, 0, 0,216, 0, 0, 0, 18, 0, 0, 0, +228, 0, 0, 0, 0, 0, 0, 0,198, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,198, 0, 0, 0, 18, 0, 0, 0, +228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 18, 2, 0, 0, + 2, 0, 3, 3, 0, 0, 12, 4, 6, 0,216, 0,229, 0,199, 0,211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 61, 1, 0, 0, 33, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,216, 0,229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 1, 0, 0,168, 13,195, 6, 0, 0, 0, 0,183, 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, 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, 8, 15,195, 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, 1, 0, 0, 0, 68, 65, 84, 65, + 16, 0, 0, 0, 8, 15,195, 6, 0, 0, 0, 0,237, 0, 0, 0, 1, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0,104, 15,195, 6, + 0, 0, 0, 0, 68, 65, 84, 65,224, 0, 0, 0,104, 15,195, 6, 0, 0, 0, 0,236, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 19, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 20, 0, 0, 0, + 1, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 21, 0, 1, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0,248, 64,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,104, 74,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 8,129,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 72, 88,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 88,110,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,168, 81,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 56, 60,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,200, 67,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 40, 59,198, 6, 0, 0, 0, 0, 21, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 68, 65, 84, 65, +160, 0, 0, 0,152, 16,195, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 40, 30,195, 6, 0, 0, 0, 0,216, 9,195, 6, + 0, 0, 0, 0, 56,217,194, 6, 0, 0, 0, 0,168,217,194, 6, 0, 0, 0, 0, 8,215,194, 6, 0, 0, 0, 0,200,216,194, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 1, 0, 0, 23, 4, 0, 0, 89, 0, 0, 0,194, 2, 0, 0, 1, 1, 87, 2, +106, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 28,195, 6, 0, 0, 0, 0,120, 28,195, 6, + 0, 0, 0, 0,136, 17,195, 6, 0, 0, 0, 0, 72, 23,195, 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, 68, 65, 84, 65, 40, 1, 0, 0,136, 17,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,248, 18,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 64,113, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,192, 21, 68, 0, 0, 0, 0, 0, 0,208, 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, + 86, 2, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128, 21, 68, 0, 0,200, 65, 0,128, 21, 68, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 87, 2, 26, 0, 87, 2, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 1, 0, 0, 23, 4, 0, 0, 89, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 2, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,248, 18,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,104, 20,195, 6, 0, 0, 0, 0,136, 17,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15, 67, 0, 64, 70,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67,255,127, 70,196, 0, 0, 0, 0,143, 0, 0, 0, +160, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +142, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0, 44, 3,143, 0, 26, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 1, 0, 0,193, 1, 0, 0,115, 0, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 80, 2, 0, 0, 5, 0, 3, 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, 68, 65, 84, 65, 40, 1, 0, 0,104, 20,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216, 21,195, 6, 0, 0, 0, 0,248, 18,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 67, 0, 0,206,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, 0, 0,206,194, 0, 0, 0, 0,143, 0, 0, 0, +160, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +142, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0,102, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 1, 0, 0,193, 1, 0, 0,115, 0, 0, 0,115, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 6, 0, 34, 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, 68, 65, 84, 65, 40, 1, 0, 0,216, 21,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 72, 23,195, 6, 0, 0, 0, 0,104, 20,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 35, 67, 0,128, 96,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0,128, 96,196, 0, 0, 0, 0,163, 0, 0, 0, +180, 0, 0, 0, 18, 0, 0, 0,147, 3, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +162, 0, 0, 0, 18, 0, 0, 0,147, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,180, 0,148, 3,163, 0,130, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, 0, 0, 23, 4, 0, 0,115, 0, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72, 23,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 21,195, 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,193, 1, 0, 0, 23, 4, 0, 0,115, 0, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 2, 80, 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,184, 24,195, 6, 0, 0, 0, 0, 68, 65, 84, 65,112, 3, 0, 0,184, 24,195, 6, + 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +200,167,141, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 13,128,191, 0, 0,128,191, 0, 0, 0, 0, + 0, 0, 0, 0, 74,215, 76,190, 0, 0, 0, 0, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63, +143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,214,211,111,193, 0, 0,128, 63, 69,239,209, 62, 70,119,105, 63,176, 84, 89,188, 0, 0, 0, 0, 53,177,205,190, +142, 74, 70, 62,166, 33,101, 63, 0, 0, 0, 0,185,158, 81, 63, 35, 44,185,190, 43, 61,228, 62, 0, 0, 0, 0,164, 96, 68, 65, +111,121,173,192,248,209,213, 64, 0, 0,128, 63,178,157,229, 62,209,162,227,190, 48,180, 81,191,184,158, 81,191,117, 90,127, 63, + 13,114, 91, 62, 26, 63,185, 62, 35, 44,185, 62,145,180,109,188,105,147,125, 63,138, 84,228,190, 42, 61,228,190, 0, 0, 0, 0, + 0, 0, 0, 0, 9,185,108, 65,214,211,111, 65, 99,240,191, 62,110,116, 85, 63, 64,185, 70,188, 0, 0, 82,180, 48,221,185,190, + 44, 45, 51, 62, 28, 11, 79, 63, 0, 0, 56,179, 67,108,117,194,183,204,216, 65,105,156, 5,194,212,247,159,192,235, 62,114, 66, + 59,254,213,193,158,225, 3, 66, 55, 8,160, 64, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63, +143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,214,211,111,193, 0, 0,128, 63,178,157,229, 62,209,162,227,190, 48,180, 81,191,184,158, 81,191,117, 90,127, 63, + 13,114, 91, 62, 26, 63,185, 62, 35, 44,185, 62,145,180,109,188,105,147,125, 63,138, 84,228,190, 42, 61,228,190, 0, 0, 0, 0, + 0, 0, 0, 0, 9,185,108, 65,214,211,111, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,163, 91, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12,163, 91, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,163, 91, 64, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, 3,236,234,190,214,211,111, 65, +214,211,111, 65, 0, 0, 0, 0, 0, 0, 0, 0,236, 15, 72, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 32, 33, 12, 66, 86,152,137, 66,113, 27,126, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 96, 1, 0, 0,120, 28,195, 6, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, +205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200, 67,198, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, 8, 8,128, 0, 0, 0, 12, 66, 0, 0,128, 63, +205,204,204, 61, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 10, 0, 7, 1, 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, 68, 65, 84, 65,160, 0, 0, 0, 40, 30,195, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,216, 38,195, 6, 0, 0, 0, 0,152, 16,195, 6, 0, 0, 0, 0, 88,216,194, 6, + 0, 0, 0, 0, 24,218,194, 6, 0, 0, 0, 0,136,218,194, 6, 0, 0, 0, 0, 56,217,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,191, 1, 0, 0, 89, 0, 0, 0, 3, 1, 0, 0, 2, 2,192, 1,171, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 36,195, 6, 0, 0, 0, 0,216, 36,195, 6, 0, 0, 0, 0, 24, 31,195, 6, + 0, 0, 0, 0,104, 35,195, 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, 68, 65, 84, 65, 40, 1, 0, 0, 24, 31,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,136, 32,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 89, 68, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0,224, 67, 0, 0, 0, 0, 0, 0,208, 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,191, 1, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,128,223, 67, 0, 0,200, 65, 0,128,223, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,192, 1, 26, 0,192, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,191, 1, 0, 0, 89, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,192, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,136, 32,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,248, 33,195, 6, 0, 0, 0, 0, 24, 31,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 67, 0, 0,112,193, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 67, 0, 0,254,194, 0, 0, 0, 0,200, 0, 0, 0,217, 0, 0, 0, 18, 0, 0, 0, +144, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, 18, 0, 0, 0, +144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 10, 6, 0, 0, + 2, 0, 3, 3, 0, 0, 0, 4, 6, 0,217, 0,145, 0,200, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,216, 0, 0, 0,115, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,217, 0,145, 0, 0, 0, 2, 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, 68, 65, 84, 65, 40, 1, 0, 0,248, 33,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,104, 35,195, 6, 0, 0, 0, 0,136, 32,195, 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,191, 1, 0, 0,191, 1, 0, 0,115, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0,104, 35,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 33,195, 6, 0, 0, 0, 0, 0, 0, 16,193, 0, 0,130, 67, 0, 0,160,192, + 0, 0,160, 64, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 16,193, 0, 0, 32, 65, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, +144, 0, 0, 0, 18, 0, 0, 0,230, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0,230, 0, 0, 0, 18, 0, 0, 0, +144, 0, 0, 0,111, 18,131, 58,111, 18,131, 58, 0,124,146, 72, 0, 80, 67, 71, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0,231, 0,145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,217, 0, 0, 0,191, 1, 0, 0,115, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,231, 0,145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,240, 0, 0, 0,216, 36,195, 6, 0, 0, 0, 0,178, 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, 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, 24, 38,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,112, 0, 0, 0, 24, 38,195, 6, + 0, 0, 0, 0, 37, 1, 0, 0, 1, 0, 0, 0,104, 38,198, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, +160, 0, 0, 0,216, 38,195, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,168, 45,195, 6, 0, 0, 0, 0, 40, 30,195, 6, + 0, 0, 0, 0, 24,218,194, 6, 0, 0, 0, 0,184,213,194, 6, 0, 0, 0, 0,168,217,194, 6, 0, 0, 0, 0,136,218,194, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 1, 0, 0, 5, 1, 0, 0,194, 2, 0, 0, 12, 12,192, 1, +190, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 44,195, 6, 0, 0, 0, 0, 24, 44,195, 6, + 0, 0, 0, 0,200, 39,195, 6, 0, 0, 0, 0,168, 42,195, 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, 68, 65, 84, 65, 40, 1, 0, 0,200, 39,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 56, 41,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,192, 94, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,224, 67, 0, 0, 0, 0, 0, 0,208, 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, +191, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,223, 67, 0, 0,200, 65, 0,128,223, 67, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,192, 1, 26, 0,192, 1, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 1, 0, 0, 5, 1, 0, 0, 30, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56, 41,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,168, 42,195, 6, 0, 0, 0, 0,200, 39,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 55, 67, 0, 0, 0,194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 67, 0, 0,201,195, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +199, 0, 0, 0, 18, 0, 0, 0,163, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 8, 4, 0, 0, 2, 0, 3, 3, 0, 0, 2, 4, 6, 0,200, 0,164, 1,200, 0,146, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, 31, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 0,164, 1, 0, 0, 2, 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, 68, 65, 84, 65, 40, 1, 0, 0,168, 42,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 41,195, 6, 0, 0, 0, 0, 0, 0, 32,193, + 0, 0,104, 68, 0, 0, 72,194, 0, 0, 0, 0, 0, 0, 32,193, 0, 0,104, 68, 0, 0,201,195, 0, 0, 0, 0,231, 0, 0, 0, +248, 0, 0, 0, 18, 0, 0, 0,163, 1, 0, 0, 0, 0, 0, 0,230, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +230, 0, 0, 0, 18, 0, 0, 0,163, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124,146, 72, 0, 64, 28, 70, 10,215, 35, 60, + 0, 0, 72, 66, 74, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 4, 4, 0,248, 0,164, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 0, 0, 0,191, 1, 0, 0, 31, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 0,164, 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, 68, 65, 84, 65, 72, 1, 0, 0, 24, 44,195, 6, + 0, 0, 0, 0, 38, 1, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 38,198, 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, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,168, 45,195, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 38,195, 6, 0, 0, 0, 0,248,218,194, 6, + 0, 0, 0, 0, 8,215,194, 6, 0, 0, 0, 0, 40,214,194, 6, 0, 0, 0, 0,104,219,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 61, 2, 0, 0,194, 2, 0, 0, 1, 1,216, 0,134, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 53,195, 6, 0, 0, 0, 0, 56, 53,195, 6, 0, 0, 0, 0,152, 46,195, 6, + 0, 0, 0, 0, 8, 48,195, 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, 68, 65, 84, 65, 40, 1, 0, 0,152, 46,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 8, 48,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 68, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0,165, 67, 0, 0, 0, 64, 0, 0,208, 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, 73, 1, 0, 0, 0, 0, 0, 0, + 23, 0, 0, 0, 0,128,164, 67, 0, 0,200, 65, 0,128,164, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 74, 1, 24, 0, 74, 1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 4, 0, 0,240, 4, 0, 0, 61, 2, 0, 0, 61, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 8, 48,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 46,195, 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, 25, 4, 0, 0,240, 4, 0, 0, 61, 2, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,216, 0,134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 49,195, 6, 0, 0, 0, 0, 68, 65, 84, 65,112, 3, 0, 0,120, 49,195, 6, 0, 0, 0, 0,173, 0, 0, 0, + 1, 0, 0, 0, 56,255, 13, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,228,100, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 65,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0, 72, 1, 77,190, + 0, 0, 0, 0,221,149, 47, 63, 86,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63,225,251,159, 62,149, 84, 28,191, + 0, 0, 0, 0,192, 56, 49,188, 55, 53,101, 63, 52,247,227, 62, 0, 0, 0, 0, 90, 38,173,190, 0,222,192,190,152, 9, 52,193, + 0, 0,128, 63,223,149, 47, 63, 55, 70, 58, 63,160, 56, 49,188, 0, 0, 0, 0, 88,126,162,190,229,251,159, 62, 55, 53,101, 63, + 0, 0, 0, 0, 7,165, 39, 63,150, 84, 28,191, 51,247,227, 62, 0, 0, 0, 0,110,101,239, 64,151, 62,208,192, 78,255,170, 64, + 0, 0,128, 63, 47,201,194, 63, 61, 73,145,191,244,250, 39,191, 8,165, 39,191,190,164,206, 63,209, 10,143, 63,180,164, 28, 63, +149, 84, 28, 63,224,153,196,188,136,239, 76, 64, 10,108,228,190, 52,247,227,190,125, 21, 64,191,126,113,172,191,216, 49, 49, 65, +152, 9, 52, 65,149, 70,158, 62, 24,234,167, 62,192,214,159,187, 0, 0, 6,181,196,188,181,189, 71,238,178, 61,127, 45,128, 62, + 0, 0,226, 51,168,120, 21,194,107, 5, 2, 66,203,135,213,193,147,214,159,192,177, 38, 19, 66,124,173,255,193, 96,101,210, 65, +128, 40,160, 64,221,149, 47, 63, 86,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63,225,251,159, 62,149, 84, 28,191, + 0, 0, 0, 0,192, 56, 49,188, 55, 53,101, 63, 52,247,227, 62, 0, 0, 0, 0, 90, 38,173,190, 0,222,192,190,152, 9, 52,193, + 0, 0,128, 63, 47,201,194, 63, 61, 73,145,191,244,250, 39,191, 8,165, 39,191,190,164,206, 63,209, 10,143, 63,180,164, 28, 63, +149, 84, 28, 63,224,153,196,188,136,239, 76, 64, 10,108,228,190, 52,247,227,190,125, 21, 64,191,126,113,172,191,216, 49, 49, 65, +152, 9, 52, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,103, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,103, 97, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,103, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63,241, 22, 72, 63, 78,162,246,190, 43, 8, 90,190, 2, 35,171,190, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,253,191,136, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 65, 1, 2, 0, 0,255,255, 0, 0, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0,128, 63,190,133, 65, 66, 99,212, 90, 66, + 27,183,118, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 1, 0, 0, 56, 53,195, 6, + 0, 0, 0, 0,174, 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, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65,205,204, 76, 62, 2, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200, 67,198, 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, 1, 0, 0, 0, + 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 3, 0, 8, 0,128, 0, 0, 0, 12, 66, 0, 0,128, 63, 10,215, 35, 60, 0, 0,250, 67, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 10, 0, 7, 1, + 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, 83, 78, 0, 0, 8, 1, 0, 0,120, 55,195, 6, 0, 0, 0, 0,210, 0, 0, 0, + 1, 0, 0, 0,248,163,195, 6, 0, 0, 0, 0,136,211,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 82, 67,111,109,112,111,115,105,116,105,110,103, 0,103, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 56,195, 6, + 0, 0, 0, 0,120, 62,195, 6, 0, 0, 0, 0,232, 62,195, 6, 0, 0, 0, 0, 24, 72,195, 6, 0, 0, 0, 0,136, 72,195, 6, + 0, 0, 0, 0,184,124,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 32, 0, 0, 0,200, 56,195, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0, 56, 57,195, 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, 68, 65, 84, 65, 32, 0, 0, 0, 56, 57,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,168, 57,195, 6, + 0, 0, 0, 0,200, 56,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,168, 57,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 24, 58,195, 6, 0, 0, 0, 0, 56, 57,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 24, 58,195, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136, 58,195, 6, 0, 0, 0, 0,168, 57,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,136, 58,195, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,248, 58,195, 6, 0, 0, 0, 0, 24, 58,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,234, 3, + 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,248, 58,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104, 59,195, 6, + 0, 0, 0, 0,136, 58,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,104, 59,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,216, 59,195, 6, 0, 0, 0, 0,248, 58,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6, 92, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,216, 59,195, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 60,195, 6, 0, 0, 0, 0,104, 59,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,126, 7, 92, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 72, 60,195, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,184, 60,195, 6, 0, 0, 0, 0,216, 59,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6,234, 3, + 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,184, 60,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40, 61,195, 6, + 0, 0, 0, 0, 72, 60,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0, 40, 61,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,152, 61,195, 6, 0, 0, 0, 0,184, 60,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,152, 61,195, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8, 62,195, 6, 0, 0, 0, 0, 40, 61,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 3,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8, 62,195, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,120, 62,195, 6, 0, 0, 0, 0,152, 61,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,120, 62,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 62,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,232, 62,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88, 63,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 57,195, 6, 0, 0, 0, 0,168, 57,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0, 88, 63,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200, 63,195, 6, 0, 0, 0, 0,232, 62,195, 6, + 0, 0, 0, 0, 56, 57,195, 6, 0, 0, 0, 0,136, 58,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,200, 63,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56, 64,195, 6, 0, 0, 0, 0, 88, 63,195, 6, + 0, 0, 0, 0,168, 57,195, 6, 0, 0, 0, 0,248, 58,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0, 56, 64,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168, 64,195, 6, 0, 0, 0, 0,200, 63,195, 6, + 0, 0, 0, 0,136, 58,195, 6, 0, 0, 0, 0,248, 58,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,168, 64,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24, 65,195, 6, 0, 0, 0, 0, 56, 64,195, 6, + 0, 0, 0, 0, 24, 58,195, 6, 0, 0, 0, 0,216, 59,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0, 24, 65,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136, 65,195, 6, 0, 0, 0, 0,168, 64,195, 6, + 0, 0, 0, 0,104, 59,195, 6, 0, 0, 0, 0,216, 59,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,136, 65,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248, 65,195, 6, 0, 0, 0, 0, 24, 65,195, 6, + 0, 0, 0, 0,248, 58,195, 6, 0, 0, 0, 0, 72, 60,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,248, 65,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104, 66,195, 6, 0, 0, 0, 0,136, 65,195, 6, + 0, 0, 0, 0,136, 58,195, 6, 0, 0, 0, 0, 72, 60,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,104, 66,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216, 66,195, 6, 0, 0, 0, 0,248, 65,195, 6, + 0, 0, 0, 0,104, 59,195, 6, 0, 0, 0, 0, 72, 60,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,216, 66,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72, 67,195, 6, 0, 0, 0, 0,104, 66,195, 6, + 0, 0, 0, 0,248, 58,195, 6, 0, 0, 0, 0,216, 59,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0, 72, 67,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184, 67,195, 6, 0, 0, 0, 0,216, 66,195, 6, + 0, 0, 0, 0,136, 58,195, 6, 0, 0, 0, 0,184, 60,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,184, 67,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40, 68,195, 6, 0, 0, 0, 0, 72, 67,195, 6, + 0, 0, 0, 0, 72, 60,195, 6, 0, 0, 0, 0, 40, 61,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0, 40, 68,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152, 68,195, 6, 0, 0, 0, 0,184, 67,195, 6, + 0, 0, 0, 0,184, 60,195, 6, 0, 0, 0, 0, 40, 61,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,152, 68,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8, 69,195, 6, 0, 0, 0, 0, 40, 68,195, 6, + 0, 0, 0, 0,184, 60,195, 6, 0, 0, 0, 0,152, 61,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0, 8, 69,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120, 69,195, 6, 0, 0, 0, 0,152, 68,195, 6, + 0, 0, 0, 0, 40, 61,195, 6, 0, 0, 0, 0,152, 61,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,120, 69,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232, 69,195, 6, 0, 0, 0, 0, 8, 69,195, 6, + 0, 0, 0, 0,200, 56,195, 6, 0, 0, 0, 0, 8, 62,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,232, 69,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88, 70,195, 6, 0, 0, 0, 0,120, 69,195, 6, + 0, 0, 0, 0, 8, 62,195, 6, 0, 0, 0, 0,120, 62,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0, 88, 70,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200, 70,195, 6, 0, 0, 0, 0,232, 69,195, 6, + 0, 0, 0, 0, 24, 58,195, 6, 0, 0, 0, 0,120, 62,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,200, 70,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56, 71,195, 6, 0, 0, 0, 0, 88, 70,195, 6, + 0, 0, 0, 0,104, 59,195, 6, 0, 0, 0, 0,120, 62,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0, 56, 71,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168, 71,195, 6, 0, 0, 0, 0,200, 70,195, 6, + 0, 0, 0, 0,152, 61,195, 6, 0, 0, 0, 0, 8, 62,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0,168, 71,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24, 72,195, 6, 0, 0, 0, 0, 56, 71,195, 6, + 0, 0, 0, 0, 40, 61,195, 6, 0, 0, 0, 0,120, 62,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 0, 0, 0, 24, 72,195, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 71,195, 6, + 0, 0, 0, 0,200, 56,195, 6, 0, 0, 0, 0,184, 60,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, +160, 0, 0, 0,136, 72,195, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 88, 76,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,136, 58,195, 6, 0, 0, 0, 0, 56, 57,195, 6, 0, 0, 0, 0,168, 57,195, 6, 0, 0, 0, 0,248, 58,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,235, 3, 0, 0, 5, 4, 0, 0, 7, 7,127, 7, + 27, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,163,195, 6, 0, 0, 0, 0,104,163,195, 6, + 0, 0, 0, 0,120, 73,195, 6, 0, 0, 0, 0,232, 74,195, 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, 68, 65, 84, 65, 40, 1, 0, 0,120, 73,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,232, 74,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32,148, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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, +126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,235, 3, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,232, 74,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 73,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0,240,109, 69, 0, 0,128,192, 0, 0, 0, 0, 0, 0, 0, 0,255,255,109, 69, 0, 0, 0,192, 0, 0, 0, 0,112, 7, 0, 0, +129, 7, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +111, 7, 0, 0, 18, 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,128, 63, + 0, 0,128, 63, 2, 0, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,129, 7, 2, 0,112, 7, 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, 5, 4, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65,160, 0, 0, 0, 88, 76,195, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 72, 81,195, 6, 0, 0, 0, 0,136, 72,195, 6, 0, 0, 0, 0,120, 62,195, 6, + 0, 0, 0, 0,104, 59,195, 6, 0, 0, 0, 0,216, 59,195, 6, 0, 0, 0, 0, 24, 58,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 91, 0, 0, 0, 15, 15, 94, 1, 92, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 80,195, 6, 0, 0, 0, 0, 40, 80,195, 6, 0, 0, 0, 0, 72, 77,195, 6, + 0, 0, 0, 0,184, 78,195, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72, 77,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,184, 78,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,115, 68, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0,175, 67, 0, 0, 0, 0, 0, 0,208, 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, 93, 1, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,128,174, 67, 0, 0,200, 65, 0,128,174, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 94, 1, 26, 0, 94, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,184, 78,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 77,195, 6, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, + 0, 0, 72, 66, 50, 51, 74,193,154,209,131, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 93, 1, 0, 0, 18, 0, 0, 0, + 65, 0, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, 72, 0, 0, 0, + 0, 0, 0, 2, 4, 0, 0, 4, 8, 0, 94, 1, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 26, 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 1, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,208, 0, 0, 0, 40, 80,195, 6, 0, 0, 0, 0,190, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 72, 81,195, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,216,105,195, 6, 0, 0, 0, 0, 88, 76,195, 6, 0, 0, 0, 0,104, 59,195, 6, + 0, 0, 0, 0, 72, 60,195, 6, 0, 0, 0, 0,248, 58,195, 6, 0, 0, 0, 0,216, 59,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 93, 0, 0, 0,233, 3, 0, 0, 4, 4, 94, 1,141, 3, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,104,195, 6, 0, 0, 0, 0,152,104,195, 6, 0, 0, 0, 0, 56, 82,195, 6, + 0, 0, 0, 0,168, 83,195, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56, 82,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,168, 83,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148, 67, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0,175, 67, 0, 0, 0, 0, 0, 0,208, 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, 93, 1, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,128,174, 67, 0, 0,200, 65, 0,128,174, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 94, 1, 26, 0, 94, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0,208, 3, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,168, 83,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 82,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,174, 67, 0,128, 92,196, + 0, 0, 0, 0, 0, 0, 0, 0,255,127,166, 67,255,191, 92,196, 0, 0, 0, 0, 77, 1, 0, 0, 94, 1, 0, 0, 0, 0, 0, 0, +114, 3, 0, 0, 0, 0, 0, 0, 82, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 0, 0, +114, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, + 1, 0, 7, 0, 18, 0, 0, 4, 6, 0, 94, 1,115, 3, 77, 1,115, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 93, 0, 0, 0,207, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 1,115, 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, 24, 85,195, 6, + 0, 0, 0, 0,248,102,195, 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, 68, 65, 84, 65, 88, 1, 0, 0, 24, 85,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,184, 86,195, 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, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, 67,111,110,116,101,120,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,220,255, 76, 1, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0,184, 86,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 88, 88,195, 6, 0, 0, 0, 0, 24, 85,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101, +110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101, +110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255, 76, 1, 61, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 88, 88,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,248, 89,195, 6, 0, 0, 0, 0,184, 86,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,255, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,248, 89,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,152, 91,195, 6, 0, 0, 0, 0, 88, 88,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105, +109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105, +109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101,110,115,105,111,110,115, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140,254, 76, 1,203, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,152, 91,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 56, 93,195, 6, 0, 0, 0, 0,248, 89,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 65,110,116,105, 45, 65,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 58,254, 76, 1, 58, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0, 56, 93,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,216, 94,195, 6, 0, 0, 0, 0,152, 91,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111, +116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111, +116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97,109,112,108,101,100, 32, 77,111,116,105, +111,110, 32, 66,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,254, 76, 1, 0, 0, 20, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,216, 94,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,120, 96,195, 6, 0, 0, 0, 0, 56, 93,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10,254, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,120, 96,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 24, 98,195, 6, 0, 0, 0, 0,216, 94,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101, +114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101, +114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,242,253, 76, 1, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 24, 98,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,184, 99,195, 6, 0, 0, 0, 0,120, 96,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80,111,115,116, 32, 80,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,218,253, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,184, 99,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 88,101,195, 6, 0, 0, 0, 0, 24, 98,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, + 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, + 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194,253, 76, 1, 0, 0, 20, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 88,101,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,248,102,195, 6, 0, 0, 0, 0,184, 99,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, 79,117,116,112,117,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, 40,253, 76, 1,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,248,102,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,101,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97, +107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97, +107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,253, 76, 1, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,152,104,195, 6, 0, 0, 0, 0,179, 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, 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, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,255, 21, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, +160, 0, 0, 0,216,105,195, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,104,119,195, 6, 0, 0, 0, 0, 72, 81,195, 6, + 0, 0, 0, 0, 8, 62,195, 6, 0, 0, 0, 0,152, 61,195, 6, 0, 0, 0, 0, 40, 61,195, 6, 0, 0, 0, 0,120, 62,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, 0, 31, 6, 0, 0, 0, 0, 0, 0,139, 1, 0, 0, 1, 1, 27, 3, +140, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,117,195, 6, 0, 0, 0, 0,184,117,195, 6, + 0, 0, 0, 0,200,106,195, 6, 0, 0, 0, 0,136,112,195, 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, 68, 65, 84, 65, 40, 1, 0, 0,200,106,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 56,108,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 64,113, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,192, 70, 68, 0, 0, 0, 0, 0, 0,208, 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, + 26, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128, 70, 68, 0, 0,200, 65, 0,128, 70, 68, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 27, 3, 26, 0, 27, 3, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, 0, 31, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 3, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56,108,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,168,109,195, 6, 0, 0, 0, 0,200,106,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15, 67, 0, 64, 70,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67,255,127, 70,196, 0, 0, 0, 0,143, 0, 0, 0, +160, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +142, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0, 44, 3,143, 0, 26, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, 0, 5, 3, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,114, 1, 0, 0, 5, 0, 3, 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, 68, 65, 84, 65, 40, 1, 0, 0,168,109,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 24,111,195, 6, 0, 0, 0, 0, 56,108,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 67, 0, 0,206,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, 0, 0,206,194, 0, 0, 0, 0,143, 0, 0, 0, +160, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +142, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0,102, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, 0, 31, 6, 0, 0, 26, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 6, 0, 34, 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, 68, 65, 84, 65, 40, 1, 0, 0, 24,111,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,136,112,195, 6, 0, 0, 0, 0,168,109,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 35, 67, 0,192,108,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0, 0,184,195, 0, 0, 0, 0,163, 0, 0, 0, +180, 0, 0, 0, 18, 0, 0, 0,129, 1, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +162, 0, 0, 0, 18, 0, 0, 0,129, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,180, 0,130, 1,163, 0,112, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 6, 0, 0, 31, 6, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0,136,112,195, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,111,195, 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, 5, 3, 0, 0, 31, 6, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 3,114, 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,248,113,195, 6, 0, 0, 0, 0, 68, 65, 84, 65,112, 3, 0, 0,248,113,195, 6, + 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0, 93,101,230, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 30,133,119, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 65,128,191, 0, 0,128,191, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 1, 77,190, 0, 0, 0, 0,221,149, 47, 63, 85,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63, +225,251,159, 62,149, 84, 28,191, 0, 0, 0, 0,191, 56, 49,188, 54, 53,101, 63, 50,247,227, 62, 0, 0, 0, 0, 90, 38,173,190, +254,221,192,190,152, 9, 52,193, 0, 0,128, 63,223,149, 47, 63, 55, 70, 58, 63,192, 56, 49,188, 0, 0, 0, 0, 87,126,162,190, +228,251,159, 62, 56, 53,101, 63, 0, 0, 0, 0, 7,165, 39, 63,150, 84, 28,191, 50,247,227, 62, 0, 0, 0, 0,110,101,239, 64, +151, 62,208,192, 77,255,170, 64, 0, 0,128, 63, 42, 6,158, 63, 99, 28,157,191,244,250, 39,191, 8,165, 39,191,211,164,167, 63, + 55,175,154, 63,180,164, 28, 63,149, 84, 28, 63, 39,127,159,188,135,157, 93, 64, 8,108,228,190, 50,247,227,190, 4,213, 27,191, +122,122,186,191,216, 49, 49, 65,152, 9, 52, 65, 25, 25,195, 62,176,249,206, 62,128,238,196,187, 0, 0,192,179, 55, 15,168,189, +201,118,165, 61,152, 15,109, 62, 0, 0,152, 51,211,120, 21,194,144, 5, 2, 66, 6,136,213,193,193,214,159,192,219, 38, 19, 66, +196,173,255,193,154,101,210, 65,173, 40,160, 64,221,149, 47, 63, 85,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63, +225,251,159, 62,149, 84, 28,191, 0, 0, 0, 0,191, 56, 49,188, 54, 53,101, 63, 50,247,227, 62, 0, 0, 0, 0, 90, 38,173,190, +254,221,192,190,152, 9, 52,193, 0, 0,128, 63, 42, 6,158, 63, 99, 28,157,191,244,250, 39,191, 8,165, 39,191,211,164,167, 63, + 55,175,154, 63,180,164, 28, 63,149, 84, 28, 63, 39,127,159,188,135,157, 93, 64, 8,108,228,190, 50,247,227,190, 4,213, 27,191, +122,122,186,191,216, 49, 49, 65,152, 9, 52, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,250,150, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 62,250,150, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,250,150, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,241, 22, 72, 63, 78,162,246,190, 44, 8, 90,190, 3, 35,171,190,214,211,111, 65, +214,211,111, 65, 0, 0, 0, 0, 0, 0, 0, 0, 80, 49,183, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 65, + 1, 2, 0, 0,255,255, 0, 0, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, 3,236,234,190, 1, 0, 0, 0, 0, 0,128, 63, +190,133, 65, 66,100,212, 90, 66, 31,183,118, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 96, 1, 0, 0,184,117,195, 6, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, +205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200, 67,198, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, 8, 8,128, 0, 0, 0, 12, 66, 0, 0,128, 63, +205,204,204, 61, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 10, 0, 7, 1, 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, 68, 65, 84, 65,160, 0, 0, 0,104,119,195, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,184,124,195, 6, 0, 0, 0, 0,216,105,195, 6, 0, 0, 0, 0,184, 60,195, 6, + 0, 0, 0, 0,136, 58,195, 6, 0, 0, 0, 0, 72, 60,195, 6, 0, 0, 0, 0, 40, 61,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 6, 0, 0,141, 1, 0, 0,233, 3, 0, 0, 16, 16, 32, 6, 93, 2, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,123,195, 6, 0, 0, 0, 0, 56,123,195, 6, 0, 0, 0, 0, 88,120,195, 6, + 0, 0, 0, 0,200,121,195, 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, 68, 65, 84, 65, 40, 1, 0, 0, 88,120,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,200,121,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 66, 68, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0,196, 68, 0, 0, 0, 0, 0, 0,208, 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, 31, 6, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,224,195, 68, 0, 0,200, 65, 0,224,195, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 32, 6, 26, 0, 32, 6, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 6, 0, 0,141, 1, 0, 0,166, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32, 6, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,200,121,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,120,195, 6, 0, 0, 0, 0, 0, 0, 32,193, 0, 0, 0, 68, 0, 0, 32,193, + 0, 0, 0, 68,128,195,217,195,192,225,108, 68, 96,240,187, 64, 62, 16,253, 67, 15, 6, 0, 0, 32, 6, 0, 0, 18, 0, 0, 0, + 66, 2, 0, 0, 0, 0, 0, 0, 14, 6, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 14, 6, 0, 0, 18, 0, 0, 0, + 66, 2, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,250, 70, 0, 0,250, 70,236, 81,184, 61, 10,215, 19, 64, 10, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 32, 6, 67, 2, 15, 6, 49, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 6, 0, 0,167, 1, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32, 6, 67, 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, 68, 65, 84, 65, 48, 1, 0, 0, 56,123,195, 6, 0, 0, 0, 0,191, 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, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10,215, 19, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10,206, 97, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,184,124,195, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,119,195, 6, 0, 0, 0, 0,200, 56,195, 6, + 0, 0, 0, 0,184, 60,195, 6, 0, 0, 0, 0,152, 61,195, 6, 0, 0, 0, 0, 8, 62,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0,139, 1, 0, 0, 6, 6, 4, 3,140, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,129,195, 6, 0, 0, 0, 0,248,129,195, 6, 0, 0, 0, 0,168,125,195, 6, + 0, 0, 0, 0,136,128,195, 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, 68, 65, 84, 65, 40, 1, 0, 0,168,125,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 24,127,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,215, 67, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 65, 68, 0, 0, 0, 0, 0, 0,208, 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, 3, 3, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,192, 64, 68, 0, 0,200, 65, 0,192, 64, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 4, 3, 26, 0, 4, 3, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 3, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 24,127,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,136,128,195, 6, 0, 0, 0, 0,168,125,195, 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, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 0, 3, 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, 68, 65, 84, 65, 40, 1, 0, 0,136,128,195, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,127,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, + 0, 0,128, 67, 0, 0,129,191, 0,128, 0, 64, 0, 0,100,190, 0,128,156, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, +114, 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, 3, 3, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 3,114, 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, 68, 65, 84, 65, 40, 33, 0, 0,248,129,195, 6, 0, 0, 0, 0,184, 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, 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, +100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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,240, 65, 0, 0, 0, 0,154,153,153, 62, 0, 0, 0, 0, +100, 0, 0, 0,154,153,153, 62,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0,100, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 83, 78, 0, 0, 8, 1, 0, 0,248,163,195, 6, 0, 0, 0, 0,210, 0, 0, 0, + 1, 0, 0, 0,120,188,196, 6, 0, 0, 0, 0,120, 55,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 82, 68,101,102, 97,117,108,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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,165,195, 6, + 0, 0, 0, 0, 24,170,195, 6, 0, 0, 0, 0,136,170,195, 6, 0, 0, 0, 0,248,177,195, 6, 0, 0, 0, 0,104,178,195, 6, + 0, 0, 0, 0,120,156,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,123,114, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 72,165,195, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,184,165,195, 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, 68, 65, 84, 65, 32, 0, 0, 0,184,165,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40,166,195, 6, + 0, 0, 0, 0, 72,165,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,146, 4, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0, 40,166,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,152,166,195, 6, 0, 0, 0, 0,184,165,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,146, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,152,166,195, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8,167,195, 6, 0, 0, 0, 0, 40,166,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8,167,195, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,120,167,195, 6, 0, 0, 0, 0,152,166,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 4, + 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,120,167,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232,167,195, 6, + 0, 0, 0, 0, 8,167,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,104, 4, 1, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,232,167,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 88,168,195, 6, 0, 0, 0, 0,120,167,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 6, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 88,168,195, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200,168,195, 6, 0, 0, 0, 0,232,167,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80, 6,104, 4, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,200,168,195, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0, 56,169,195, 6, 0, 0, 0, 0, 88,168,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 6,196, 3, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 56,169,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,168,169,195, 6, + 0, 0, 0, 0,200,168,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,196, 3, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,168,169,195, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 24,170,195, 6, 0, 0, 0, 0, 56,169,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,144, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 24,170,195, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,169,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80, 6,144, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136,170,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,248,170,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,165,195, 6, 0, 0, 0, 0, 40,166,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248,170,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,104,171,195, 6, 0, 0, 0, 0,136,170,195, 6, 0, 0, 0, 0,184,165,195, 6, 0, 0, 0, 0, 8,167,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104,171,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,216,171,195, 6, 0, 0, 0, 0,248,170,195, 6, 0, 0, 0, 0, 40,166,195, 6, 0, 0, 0, 0,120,167,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,171,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 72,172,195, 6, 0, 0, 0, 0,104,171,195, 6, 0, 0, 0, 0, 8,167,195, 6, 0, 0, 0, 0,120,167,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72,172,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,184,172,195, 6, 0, 0, 0, 0,216,171,195, 6, 0, 0, 0, 0, 72,165,195, 6, 0, 0, 0, 0,232,167,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184,172,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 40,173,195, 6, 0, 0, 0, 0, 72,172,195, 6, 0, 0, 0, 0,152,166,195, 6, 0, 0, 0, 0,232,167,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,173,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,152,173,195, 6, 0, 0, 0, 0,184,172,195, 6, 0, 0, 0, 0, 8,167,195, 6, 0, 0, 0, 0, 88,168,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,152,173,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 8,174,195, 6, 0, 0, 0, 0, 40,173,195, 6, 0, 0, 0, 0,120,167,195, 6, 0, 0, 0, 0, 88,168,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8,174,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,120,174,195, 6, 0, 0, 0, 0,152,173,195, 6, 0, 0, 0, 0,232,167,195, 6, 0, 0, 0, 0,200,168,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120,174,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,232,174,195, 6, 0, 0, 0, 0, 8,174,195, 6, 0, 0, 0, 0, 88,168,195, 6, 0, 0, 0, 0,200,168,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232,174,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 88,175,195, 6, 0, 0, 0, 0,120,174,195, 6, 0, 0, 0, 0,120,167,195, 6, 0, 0, 0, 0, 56,169,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88,175,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,200,175,195, 6, 0, 0, 0, 0,232,174,195, 6, 0, 0, 0, 0,152,166,195, 6, 0, 0, 0, 0, 56,169,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,175,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 56,176,195, 6, 0, 0, 0, 0, 88,175,195, 6, 0, 0, 0, 0,200,168,195, 6, 0, 0, 0, 0, 56,169,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,176,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,168,176,195, 6, 0, 0, 0, 0,200,175,195, 6, 0, 0, 0, 0, 72,165,195, 6, 0, 0, 0, 0,168,169,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168,176,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 24,177,195, 6, 0, 0, 0, 0, 56,176,195, 6, 0, 0, 0, 0, 8,167,195, 6, 0, 0, 0, 0,168,169,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24,177,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,136,177,195, 6, 0, 0, 0, 0,168,176,195, 6, 0, 0, 0, 0, 88,168,195, 6, 0, 0, 0, 0, 24,170,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136,177,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,248,177,195, 6, 0, 0, 0, 0, 24,177,195, 6, 0, 0, 0, 0,232,167,195, 6, 0, 0, 0, 0, 24,170,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248,177,195, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,177,195, 6, 0, 0, 0, 0,168,169,195, 6, 0, 0, 0, 0, 24,170,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,104,178,195, 6, 0, 0, 0, 0,214, 0, 0, 0, + 1, 0, 0, 0, 56,182,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,167,195, 6, 0, 0, 0, 0,184,165,195, 6, + 0, 0, 0, 0, 40,166,195, 6, 0, 0, 0, 0,120,167,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +126, 7, 0, 0,105, 4, 0, 0,146, 4, 0, 0, 7, 7,127, 7, 42, 0, 1, 0, 0, 0, 0, 0, 7, 0, 8, 0, 8, 77,163, 6, + 0, 0, 0, 0,232,187,196, 6, 0, 0, 0, 0,232,187,196, 6, 0, 0, 0, 0, 88,179,195, 6, 0, 0, 0, 0,200,180,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,230, 12, 0, 73,127, 0, 0, 24,234, 12, 0, + 73,127, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 88,179,195, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,200,180,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,163, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, + 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, + 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, + 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +126, 7, 0, 0,105, 4, 0, 0,130, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, + 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 79,163, 6, + 0, 0, 0, 0,168,144,231, 0, 73,127, 0, 0,168,144,231, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,184,235, 12, 0, 73,127, 0, 0, 8,246, 12, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,200,180,195, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88,179,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,239, 68, 0, 0, 0, 0, 0, 0, 48, 65, 0, 0, 0, 0, + 1,192,237, 68, 0, 0, 0, 0, 0, 0,128, 65,110, 7, 0, 0,127, 7, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, +111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,109, 7, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 2, 2, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, + 10, 0,127, 7, 16, 0,110, 7, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +126, 7, 0, 0,131, 4, 0, 0,146, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 16, 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, 40, 78,163, 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,168,247, 12, 0, 73,127, 0, 0,120, 6, 13, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 56,182,195, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 8,223,195, 6, + 0, 0, 0, 0,104,178,195, 6, 0, 0, 0, 0,232,167,195, 6, 0, 0, 0, 0,200,168,195, 6, 0, 0, 0, 0, 56,169,195, 6, + 0, 0, 0, 0,152,166,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 6, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, +195, 3, 0, 0, 4, 4, 46, 1,196, 3, 1, 0, 0, 0, 0, 0, 0, 0, 8, 0,168, 72,163, 6, 0, 0, 0, 0,200,221,195, 6, + 0, 0, 0, 0,200,221,195, 6, 0, 0, 0, 0, 40,183,195, 6, 0, 0, 0, 0,152,184,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 13, 13, 0, 73,127, 0, 0,152, 29, 13, 0, 73,127, 0, 0, 68, 65, 84, 65, + 40, 1, 0, 0, 40,183,195, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,152,184,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,151, 67, 0, 0, 0, 0, + 0, 0,208, 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, 45, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,150, 67, 0, 0,200, 65, 0,128,150, 67, + 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 46, 1, 26, 0, 46, 1, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 6, 0, 0,126, 7, 0, 0,170, 3, 0, 0, +195, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 1, 26, 0, 4, 0, 1, 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, 24, 76,163, 6, 0, 0, 0, 0,104,215,226, 0, + 73,127, 0, 0,104,215,226, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232, 34, 13, 0, + 73,127, 0, 0, 88, 93,226, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 1, 0, 0,152,184,195, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,183,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0,128,106,196, 0, 0, 0, 0, 0, 0, 0, 0, 1,128,142, 67, 2,128,106,196, + 0, 0, 0, 0, 29, 1, 0, 0, 46, 1, 0, 0, 0, 0, 0, 0,169, 3, 0, 0, 0, 0, 0, 0, 74, 1, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 0, 0,169, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0, 46, 1,170, 3, 29, 1, +170, 3, 0, 0,248, 81,229, 0, 73,127, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 81, 6, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, +169, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 1,170, 3, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 73,163, 6, 0, 0, 0, 0, 40,189,225, 0, + 73,127, 0, 0,232, 26,225, 0, 73,127, 0, 0, 8,186,195, 6, 0, 0, 0, 0, 40,220,195, 6, 0, 0, 0, 0,248,236, 12, 0, + 73,127, 0, 0, 56,181,226, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0, 8,186,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,168,187,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,184, 74,163, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99, +111,110,116,101,120,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, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99, +111,110,116,101,120,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, 67,111,110,116,101,120,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,220,255, 29, 1, 36, 0, 0, 0, 0, 0, + 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,168,187,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 72,189,195, 6, 0, 0, 0, 0, 8,186,195, 6, 0, 0, 0, 0,168, 73, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,135,255, 29, 1, 61, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0, 72,189,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,232,190,195, 6, 0, 0, 0, 0,168,187,195, 6, + 0, 0, 0, 0, 24, 76, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97, +121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97, +121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,255, 29, 1, 0, 0, 0, 0, 0, 0, + 4, 0, 2, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,232,190,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,136,192,195, 6, 0, 0, 0, 0, 72,189,195, 6, 0, 0, 0, 0,136, 78, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,140,254, 29, 1,203, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0,136,192,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 40,194,195, 6, 0, 0, 0, 0,232,190,195, 6, + 0, 0, 0, 0,248, 80, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110, +116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110, +116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,110,116,105, 45, 65,108,105, 97,115,105,110, +103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58,254, 29, 1, 58, 0, 20, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 40,194,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,200,195,195, 6, 0, 0, 0, 0,136,192,195, 6, 0, 0, 0, 0,104, 83, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 97,109,112,108,101,100, 32, 77,111,116,105,111,110, 32, 66,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 34,254, 29, 1, 0, 0, 20, 0, 0, 0, 4, 0, 2, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,200,195,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,104,197,195, 6, 0, 0, 0, 0, 40,194,195, 6, + 0, 0, 0, 0, 72,156, 53, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, + 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, + 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,104, 97,100,105,110,103, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,254, 29, 1, 0, 0, 0, 0, 0, 0, + 4, 0, 2, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,104,197,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 8,199,195, 6, 0, 0, 0, 0,200,195,195, 6, 0, 0, 0, 0,248, 92, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,242,253, 29, 1, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0, 8,199,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,168,200,195, 6, 0, 0, 0, 0,104,197,195, 6, + 0, 0, 0, 0,104, 95, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111, +115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111, +115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,111,115,116, 32, 80,114,111, 99,101,115,115, +105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,218,253, 29, 1, 0, 0, 0, 0, 0, 0, + 4, 0, 2, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,168,200,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 72,202,195, 6, 0, 0, 0, 0, 8,199,195, 6, 0, 0, 0, 0,216, 97, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,194,253, 29, 1, 0, 0, 20, 0, 0, 0, 4, 0, 2, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0, 72,202,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,232,203,195, 6, 0, 0, 0, 0,168,200,195, 6, + 0, 0, 0, 0, 72,100, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117, +116,112,117,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, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117, +116,112,117,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, 79,117,116,112,117,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, 36,253, 29, 1,134, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,232,203,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,136,205,195, 6, 0, 0, 0, 0, 72,202,195, 6, 0, 0, 0, 0, 40,105, 76, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12,253, 29, 1, 0, 0, 0, 0, 0, 0, 4, 0, 3, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0,136,205,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 40,207,195, 6, 0, 0, 0, 0,232,203,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115, 99,101, +110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115, 99,101, +110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 99,101,110,101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255, 41, 1, 61, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 40,207,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,200,208,195, 6, 0, 0, 0, 0,136,205,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,117,110,105,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, 83, 67, 69, 78, 69, 95, 80, 84, 95,117,110,105,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, 85,110,105,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 28,255, 41, 1, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,200,208,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,104,210,195, 6, 0, 0, 0, 0, 40,207,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,107,101,121, +105,110,103, 95,115,101,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,107,101,121, +105,110,103, 95,115,101,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75,101,121,105,110,103, 32, 83,101,116,115, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191,254, 41, 1, 69, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,104,210,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 8,212,195, 6, 0, 0, 0, 0,200,208,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 71,114, 97,118,105,116,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,131,254, 41, 1, 36, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0, 8,212,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,168,213,195, 6, 0, 0, 0, 0,104,210,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115,105,109, +112,108,105,102,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115,105,109, +112,108,105,102,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,105,109,112,108,105,102,121, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27,254, 41, 1, 80, 0, 20, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,168,213,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 72,215,195, 6, 0, 0, 0, 0, 8,212,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95, 99,117,115,116,111,109, 95,112,114,111,112,115, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95, 99,117,115,116,111,109, 95,112,114,111,112,115, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 67,117,115,116,111,109, 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,223,253, 41, 1, 36, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0, 72,215,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,232,216,195, 6, 0, 0, 0, 0,168,213,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, 80, 84, 95, 99, +111,110,116,101,120,116, 95,116,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, 80, 84, 95, 99, +111,110,116,101,120,116, 95,116,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,255,187, 0,204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 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, + 5, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,232,216,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,136,218,195, 6, 0, 0, 0, 0, 72,215,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, 80, 84, 95,109, 97,112,112,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, 80, 84, 95,109, 97,112,112,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 77, 97,112,112,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 77,254,187, 0,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,136,218,195, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 40,220,195, 6, 0, 0, 0, 0,232,216,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, 80, 84, 95,105, +110,102,108,117,101,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 88, 84, 85, 82, 69, 95, 80, 84, 95,105, +110,102,108,117,101,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73,110,102,108,117,101,110, 99,101, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,223,252,187, 0, 86, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 40,220,195, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,218,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 79, 66, 74, 69, 67, 84, 95, 80, 84, 95, 99,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 79, 66, 74, 69, 67, 84, 95, 80, 84, 95, 99,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 79, 98,106,101, 99,116, 32, 67,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,160,255,187, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, +248, 0, 0, 0,200,221,195, 6, 0, 0, 0, 0,179, 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, 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, 2, 0, 1, 0, 0, 0, 0, 0, 40, 97,228, 0, 73,127, 0, 0,255, 21, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 8,223,195, 6, 0, 0, 0, 0,214, 0, 0, 0, + 1, 0, 0, 0,248,227,195, 6, 0, 0, 0, 0, 56,182,195, 6, 0, 0, 0, 0, 72,165,195, 6, 0, 0, 0, 0,168,169,195, 6, + 0, 0, 0, 0, 24,170,195, 6, 0, 0, 0, 0,232,167,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 6, 0, 0, 0, 0, 0, 0,143, 0, 0, 0, 15, 15, 80, 6,144, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 28,163, 6, + 0, 0, 0, 0,216,226,195, 6, 0, 0, 0, 0,216,226,195, 6, 0, 0, 0, 0,248,223,195, 6, 0, 0, 0, 0,104,225,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 94,226, 0, 73,127, 0, 0,216,249, 12, 0, + 73,127, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,248,223,195, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,104,225,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,146, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, + 0, 0,202, 68, 0, 0, 0, 0, 0, 0,208, 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, 79, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,224,201, 68, + 0, 0,200, 65, 0,224,201, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, + 10, 0, 80, 6, 26, 0, 80, 6, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 6, 26, 0, + 6, 0, 1, 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,136, 30,163, 6, + 0, 0, 0, 0,120,171,230, 0, 73,127, 0, 0,120,171,230, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,120, 47,225, 0, 73,127, 0, 0,216, 4, 13, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,104,225,195, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,248,223,195, 6, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 72, 66, 88,218,103,194, + 40,147,141, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 6, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 79, 6, 0, 0, 18, 0, 0, 0,117, 0, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, 72, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 4, - 8, 0,241, 4, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 4, 0, 0, 26, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 4, 42, 0, + 8, 0, 80, 6,118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 6, 0, 0, 26, 0, 0, 0,143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 6,118, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 29,163, 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, 68, 65, 84, 65,208, 0, 0, 0,200, 96,200, 3, 0, 0, 0, 0,190, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 15, 13, 0, 73,127, 0, 0, 40, 27, 13, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,208, 0, 0, 0,216,226,195, 6, 0, 0, 0, 0,190, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,120, 36,215, 3, 0, 0, 0, 0,214, 0, 0, 0, - 1, 0, 0, 0,152, 37,215, 3, 0, 0, 0, 0, 88, 35,215, 3, 0, 0, 0, 0, 8, 64,201, 3, 0, 0, 0, 0, 72, 65,201, 3, - 0, 0, 0, 0,104, 63,201, 3, 0, 0, 0, 0,136, 66,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 4, 0, 0, 69, 0, 0, 0, 91, 1, 0, 0, 8, 8,241, 4, 23, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,120,150,199, 3, 0, 0, 0, 0,120,150,199, 3, 0, 0, 0, 0,248,109,217, 3, 0, 0, 0, 0,136,160,217, 3, + 0, 0, 0, 0, 63, 0, 0, 0, 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,248,227,195, 6, 0, 0, 0, 0,214, 0, 0, 0, + 1, 0, 0, 0,120,156,196, 6, 0, 0, 0, 0, 8,223,195, 6, 0, 0, 0, 0,200,168,195, 6, 0, 0, 0, 0, 88,168,195, 6, + 0, 0, 0, 0,120,167,195, 6, 0, 0, 0, 0, 56,169,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 6, 0, 0, +126, 7, 0, 0,197, 3, 0, 0,103, 4, 0, 0, 3, 3, 46, 1,163, 0, 1, 0, 0, 0, 0, 0, 0, 0, 8, 0,120, 25,163, 6, + 0, 0, 0, 0,200,231,195, 6, 0, 0, 0, 0,200,231,195, 6, 0, 0, 0, 0,232,228,195, 6, 0, 0, 0, 0, 88,230,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 27, 13, 0, 73,127, 0, 0, 40, 88,226, 0, + 73,127, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,232,228,195, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 88,230,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,244, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, + 0, 0,151, 67, 0, 0, 0, 0, 0, 0,208, 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, 45, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,150, 67, + 0, 0,200, 65, 0,128,150, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, + 10, 0, 46, 1, 26, 0, 46, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 6, 0, 0, +126, 7, 0, 0, 78, 4, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 1, 26, 0, + 8, 0, 1, 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,136, 27,163, 6, + 0, 0, 0, 0, 56, 30,231, 0, 73,127, 0, 0, 56, 30,231, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,184, 88,226, 0, 73,127, 0, 0, 88,114,225, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 88,230,195, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,232,228,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,141, 67, 0, 0,244,194, 0, 0, 0, 0, 0, 0, 0, 0, + 0,128,142, 67, 0, 0,242,194, 0, 0, 0,192, 29, 1, 0, 0, 46, 1, 0, 0, 18, 0, 0, 0,136, 0, 0, 0, 0, 0, 0, 0, + 28, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 28, 1, 0, 0, 18, 0, 0, 0,136, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 18, 4, 0, 0, 2, 0, 3, 3, 0, 0, 12, 4, + 6, 0, 46, 1,137, 0, 29, 1,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 6, 0, 0, +126, 7, 0, 0,197, 3, 0, 0, 77, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 1,137, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 26,163, 6, + 0, 0, 0, 0,248, 69,231, 0, 73,127, 0, 0,248, 69,231, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,248,105,228, 0, 73,127, 0, 0, 8,229,225, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 24, 1, 0, 0,200,231,195, 6, 0, 0, 0, 0,183, 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, 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, 68, 65, 84, 65, 40, 1, 0, 0,248,109,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,168,111,217, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 26, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, - 0, 32,158, 68, 0, 0, 0, 0, 0, 0,208, 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,240, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0,158, 68, - 0, 0,200, 65, 0, 0,158, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, - 10, 0,241, 4, 26, 0,241, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 4, 0, 0, 69, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 4, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,104, 35,231, 0, 73,127, 0, 0,104, 35,231, 0, 73,127, 0, 0, 40,233,195, 6, 0, 0, 0, 0, 0,115,101, 32, + 83, 99,117,108,112,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, 1, 0, 0, 0, 68, 65, 84, 65, 16, 0, 0, 0, 40,233,195, 6, + 0, 0, 0, 0,237, 0, 0, 0, 1, 0, 0, 0, 42, 11, 0, 0, 42, 11, 0, 0,136,233,195, 6, 0, 0, 0, 0, 68, 65, 84, 65, +160,178, 0, 0,136,233,195, 6, 0, 0, 0, 0,236, 0, 0, 0, 42, 11, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0,104, 38,198, 6, + 0, 0, 0, 0, 19, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 20, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, + 0, 0, 0, 0, 21, 0, 1, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,248, 64,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,104, 74,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8,129,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 72, 88,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 88,110,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,168, 81,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 56, 60,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,200, 67,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 40, 59,198, 6, + 0, 0, 0, 0, 21, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,232,147,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 30, 0,255,255, 3, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,136,211,194, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,120, 55,195, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,248,163,195, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,120,188,196, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,136, 95,197, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,248,174,197, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 24,246,197, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,152,208,194, 6, 0, 0, 0, 0, 30, 0,255,255, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 24,158,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 8,154,199, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 40, 59,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 56, 60,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 70, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 71, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 72, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 73, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 74, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 75, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 76, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 77, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 78, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 79, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 80, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 81, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 82, 0, 1, 0, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 31, 0, 83, 0, 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0, 8,129,198, 6, + 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 70, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 71, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 72, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 73, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 74, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 75, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 76, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 77, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 78, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 79, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 80, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 81, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 82, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 83, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 84, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 85, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 86, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 87, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 88, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 89, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 90, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 91, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 92, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 93, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 94, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 95, 0, 1, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 31, 0, 96, 0, 1, 0, 0, 0,200, 67,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 70, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 71, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 72, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 73, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 74, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 75, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 76, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 77, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 78, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 79, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 80, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 81, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 82, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 83, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 84, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 85, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 86, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 87, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 88, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 89, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 90, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 91, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 92, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 93, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 94, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 95, 0, 1, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 31, 0, 96, 0, 1, 0, 0, 0,104, 74,198, 6, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 21, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 22, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 23, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 24, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 25, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 26, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 27, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 28, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 29, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 30, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 31, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 32, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 33, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 34, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 35, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 36, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 37, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 38, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 39, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 40, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 41, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 42, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 43, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 44, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 45, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 46, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 47, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 48, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 49, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 50, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 51, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 52, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 53, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 54, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 55, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 56, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 57, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 58, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 59, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 60, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 61, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 62, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 63, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 64, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 65, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 66, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 67, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 68, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 69, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 70, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 71, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 72, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 73, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 74, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 75, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 76, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 77, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 78, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 79, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 80, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 81, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 82, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 83, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 84, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 85, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 86, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 87, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 88, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 89, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 90, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 91, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 92, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 93, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 94, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 95, 0, 1, 0, 0, 0,168, 81,198, 6, 0, 0, 0, 0, 31, 0, 96, 0, 1, 0, 0, 0,168, 81,198, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,136,211,194, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,136,211,194, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,136,211,194, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,136,211,194, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,136,211,194, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,136,211,194, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,136,211,194, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,136,211,194, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,136,211,194, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,136,211,194, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,120, 55,195, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,120, 55,195, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,120, 55,195, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,120, 55,195, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,120, 55,195, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,120, 55,195, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,120, 55,195, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,120, 55,195, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,120, 55,195, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,120, 55,195, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,248,163,195, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,248,163,195, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,248,163,195, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,248,163,195, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,248,163,195, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,248,163,195, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,248,163,195, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,248,163,195, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,248,163,195, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,248,163,195, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,120,188,196, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,120,188,196, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,120,188,196, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,120,188,196, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,120,188,196, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,120,188,196, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,120,188,196, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,120,188,196, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,120,188,196, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,120,188,196, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,136, 95,197, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,136, 95,197, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,136, 95,197, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,136, 95,197, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,136, 95,197, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,136, 95,197, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,136, 95,197, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,136, 95,197, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,136, 95,197, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,136, 95,197, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,248,174,197, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,248,174,197, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,248,174,197, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,248,174,197, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,248,174,197, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,248,174,197, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,248,174,197, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,248,174,197, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,248,174,197, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,248,174,197, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 24,246,197, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 24,246,197, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 24,246,197, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 24,246,197, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 24,246,197, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 24,246,197, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 24,246,197, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 24,246,197, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 24,246,197, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 24,246,197, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0, 88,110,198, 6, 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,152,208,194, 6, + 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,152,208,194, 6, 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,152,208,194, 6, + 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,152,208,194, 6, 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,152,208,194, 6, + 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,152,208,194, 6, 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,152,208,194, 6, + 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,152,208,194, 6, 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,152,208,194, 6, + 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,152,208,194, 6, 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,152,208,194, 6, + 0, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 1, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 2, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 3, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 4, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 5, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 6, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 7, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 8, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 9, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 10, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 11, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 12, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 13, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 14, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 15, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 16, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 17, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 18, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 31, 0, 19, 0, 1, 0, 0, 0,248, 64,198, 6, + 0, 0, 0, 0, 31, 0, 20, 0, 1, 0, 0, 0,248, 64,198, 6, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,120,156,196, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,227,195, 6, 0, 0, 0, 0,168,169,195, 6, + 0, 0, 0, 0, 8,167,195, 6, 0, 0, 0, 0, 88,168,195, 6, 0, 0, 0, 0, 24,170,195, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 79, 6, 0, 0,145, 0, 0, 0,103, 4, 0, 0, 1, 1, 80, 6,215, 3, 1, 0, 0, 0, 0, 0, + 0, 0, 8, 0,120, 31,163, 6, 0, 0, 0, 0, 56,186,196, 6, 0, 0, 0, 0, 56,186,196, 6, 0, 0, 0, 0,104,157,196, 6, + 0, 0, 0, 0, 8,181,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,106,228, 0, + 73,127, 0, 0,104, 9, 13, 0, 73,127, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,104,157,196, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,216,158,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,108, 68, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0,202, 68, 0, 0, 0, 0, 0, 0,208, 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, 79, 6, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,224,201, 68, 0, 0,200, 65, 0,224,201, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 80, 6, 26, 0, 80, 6, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 79, 6, 0, 0,145, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80, 6, 26, 0, 10, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,216, 41,163, 6, 0, 0, 0, 0,232,105,233, 0, 73,127, 0, 0,232,105,233, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,176,229, 0, 73,127, 0, 0,104, 11, 13, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,216,158,196, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,136,176,196, 6, 0, 0, 0, 0,104,157,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0, 64, 57,196, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 64, 57,196, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, +228, 2, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, +228, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, + 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,229, 2,143, 0,229, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0,131, 1, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,160, 0,229, 2, 11, 0, 5, 0, 3, 0, 0, 0, 0, 0, 0, 0,160, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,152, 38,163, 6, 0, 0, 0, 0, 40, 93,232, 0, 73,127, 0, 0, 40, 93,232, 0, 73,127, 0, 0, 72,160,196, 6, + 0, 0, 0, 0,232,174,196, 6, 0, 0, 0, 0, 56, 12, 13, 0, 73,127, 0, 0, 88, 96,228, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 72,160,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,232,161,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,130, 79, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, 99,116,109,111,100,101, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, 99,116,109,111,100,101, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 79, 98,106,101, 99,116, 32, 84,111,111,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,233,253,143, 0,255, 1, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0,232,161,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,136,163,196, 6, 0, 0, 0, 0, 72,160,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111, +111,108,115, 95, 98,114,117,115,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111, +111,108,115, 95, 98,114,117,115,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,114,117,115,104, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,254,143, 0,115, 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, 68, 65, 84, 65, 88, 1, 0, 0,136,163,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 40,165,196, 6, 0, 0, 0, 0,232,161,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95,116,111,111,108, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95,116,111,111,108, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 84,111,111,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 74,254,143, 0, 61, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0, 40,165,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,200,166,196, 6, 0, 0, 0, 0,136,163,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111, +111,108,115, 95, 98,114,117,115,104, 95,115,116,114,111,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111, +111,108,115, 95, 98,114,117,115,104, 95,115,116,114,111,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,116,114,111,107,101, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,254,143, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,200,166,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,104,168,196, 6, 0, 0, 0, 0, 40,165,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95, 99,117,114,118,101, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95, 98,114,117,115,104, 95, 99,117,114,118,101, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 67,117,114,118,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 45,254,143, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,104,168,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 8,170,196, 6, 0, 0, 0, 0,200,166,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111, +111,108,115, 95, 98,114,117,115,104, 95, 97,112,112,101, 97,114, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111, +111,108,115, 95, 98,114,117,115,104, 95, 97,112,112,101, 97,114, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,112,112,101, 97,114, 97,110, 99,101, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,229,253,143, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 8,170,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,168,171,196, 6, 0, 0, 0, 0,104,168,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,118,101,114,116,101,120,112, 97,105,110,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, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,118,101,114,116,101,120,112, 97,105,110,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, 79,112,116,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,149,253,143, 0,146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,168,171,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 72,173,196, 6, 0, 0, 0, 0, 8,170,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111, +111,108,115, 95, 98,114,117,115,104, 95,116,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111, +111,108,115, 95, 98,114,117,115,104, 95,116,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,101,120,116,117,114,101, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93,254,143, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 72,173,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,232,174,196, 6, 0, 0, 0, 0,168,171,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,115, 99,117,108,112,116, 95,111,112,116,105,111,110,115, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,115, 99,117,108,112,116, 95,111,112,116,105,111,110,115, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 79,112,116,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21,254,143, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0,232,174,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,173,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,115, 99, +117,108,112,116, 95,115,121,109,109,101,116,114,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,115, 99, +117,108,112,116, 95,115,121,109,109,101,116,114,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,121,109,109,101,116,114,121, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253,253,143, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 40, 1, 0, 0,136,176,196, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,152,179,196, 6, 0, 0, 0, 0,216,158,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0, 0, 90,195, + 0, 0, 0, 0, 0, 0, 0, 0,227,102, 16, 67, 24, 30, 90,195, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, +215, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, +215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, + 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,216, 0,143, 0,216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0,171, 0, 0, 0,130, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,160, 0,216, 0, 12, 0, 6, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,136, 39,163, 6, 0, 0, 0, 0,200,253,232, 0, 73,127, 0, 0,200,253,232, 0, 73,127, 0, 0,248,177,196, 6, + 0, 0, 0, 0,248,177,196, 6, 0, 0, 0, 0,200, 46,228, 0, 73,127, 0, 0, 24,181,229, 0, 73,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,248,177,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 40,163, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 79,112,101,114, 97,116,111,114, 0,100,101, 0, 32, 77,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,216,255,144, 0, 16, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 40, 1, 0, 0,152,179,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 8,181,196, 6, 0, 0, 0, 0,136,176,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 67, 0, 96,158,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0, 96,158,196, + 0,128,142,195,163, 0, 0, 0,180, 0, 0, 0, 0, 0, 0, 0,213, 3, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0,213, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,180, 0,214, 3,163, 0, +214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 6, 0, 0, 79, 6, 0, 0,171, 0, 0, 0, +103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 0, 4, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 33,163, 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, 68, 65, 84, 65, + 40, 1, 0, 0, 8,181,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,179,196, 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,160, 0, 0, 0, 79, 6, 0, 0,171, 0, 0, 0, +103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,176, 5,189, 3, 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 32,163, 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,248,226,224, 0, + 73,127, 0, 0, 72, 40, 13, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,182,196, 6, 0, 0, 0, 0, 68, 65, 84, 65, +112, 3, 0, 0,120,182,196, 6, 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0, 1, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,188,255,212, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 6,128,191, + 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0, 11,210, 76,190, 0, 0, 0, 0, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, + 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33,210,111,193, 0, 0,128, 63, 68,239,209, 62, 70,119,105, 63,176, 84, 89,188, + 0, 0, 0, 0, 52,177,205,190,142, 74, 70, 62,166, 33,101, 63, 0, 0, 0, 0,185,158, 81, 63, 35, 44,185,190, 43, 61,228, 62, + 0, 0, 0, 0, 62, 95, 68, 65, 51,120,173,192,115,208,213, 64, 0, 0,128, 63,180,157,229, 62, 57, 36, 43,191,116,169, 81,191, +184,158, 81,191,118, 90,127, 63,212,251,164, 62,158, 53,185, 62, 35, 44,185, 62,147,180,109,188,194,164,190, 63,218, 72,228,190, + 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0, 33,171,108, 65, 33,210,111, 65,100,240,191, 62,110,116, 85, 63, 32,185, 70,188, + 0, 0, 80,180,122, 55,119,190, 96, 82,238, 61,227,177, 9, 63, 0, 0,248, 51,197,112,117,194,179,208,216, 65,220,158, 5,194, +231,251,159,192,221, 54,114, 66, 30,247,213,193, 58,221, 3, 66, 25, 4,160, 64, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, + 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33,210,111,193, 0, 0,128, 63,180,157,229, 62, 57, 36, 43,191,116,169, 81,191, +184,158, 81,191,118, 90,127, 63,212,251,164, 62,158, 53,185, 62, 35, 44,185, 62,147,180,109,188,194,164,190, 63,218, 72,228,190, + 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0, 33,171,108, 65, 33,210,111, 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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,182,180, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,114,182,180, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,182,180, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, + 3,236,234,190, 33,210,111, 65, 33,210,111, 65, 0, 0, 0, 0, 0, 0, 0, 0,146,156,164, 58, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 32, 33, 12, 66, 85,152,137, 66,113, 27,126, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 96, 1, 0, 0, 56,186,196, 6, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, + 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32, 65,205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200, 67,198, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, 8, 24,128, 0, + 0, 0, 12, 66, 0, 0,128, 63,205,204,204, 61, 0, 0,122, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 10, 0, 7, 1, 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, 83, 78, 0, 0, + 8, 1, 0, 0,120,188,196, 6, 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0,136, 12,197, 6, 0, 0, 0, 0,248,163,195, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 71, 97,109,101, 32, 76,111,103,105, 99, + 0, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,189,196, 6, 0, 0, 0, 0,120,195,196, 6, 0, 0, 0, 0,232,195,196, 6, + 0, 0, 0, 0,168,204,196, 6, 0, 0, 0, 0, 24,205,196, 6, 0, 0, 0, 0, 56, 5,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 32, 0, 0, 0,200,189,196, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 56,190,196, 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, 68, 65, 84, 65, 32, 0, 0, 0, 56,190,196, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,168,190,196, 6, 0, 0, 0, 0,200,189,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,168,190,196, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0, 24,191,196, 6, 0, 0, 0, 0, 56,190,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 5, 4, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 24,191,196, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136,191,196, 6, + 0, 0, 0, 0,168,190,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,136,191,196, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,248,191,196, 6, 0, 0, 0, 0, 24,191,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,248,191,196, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,104,192,196, 6, 0, 0, 0, 0,136,191,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,126, 7,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,104,192,196, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,216,192,196, 6, 0, 0, 0, 0,248,191,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 1, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,216,192,196, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72,193,196, 6, + 0, 0, 0, 0,104,192,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0, 72,193,196, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,184,193,196, 6, 0, 0, 0, 0,216,192,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,184,193,196, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40,194,196, 6, 0, 0, 0, 0, 72,193,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,126, 7,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 40,194,196, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,152,194,196, 6, 0, 0, 0, 0,184,193,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 5,140, 1, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,152,194,196, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8,195,196, 6, + 0, 0, 0, 0, 40,194,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 5,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0, 8,195,196, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,120,195,196, 6, 0, 0, 0, 0,152,194,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 1,140, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,120,195,196, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,195,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 1,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232,195,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 88,196,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,190,196, 6, 0, 0, 0, 0,168,190,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88,196,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,200,196,196, 6, 0, 0, 0, 0,232,195,196, 6, 0, 0, 0, 0, 56,190,196, 6, 0, 0, 0, 0,136,191,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,196,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 56,197,196, 6, 0, 0, 0, 0, 88,196,196, 6, 0, 0, 0, 0,168,190,196, 6, 0, 0, 0, 0,248,191,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,197,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,168,197,196, 6, 0, 0, 0, 0,200,196,196, 6, 0, 0, 0, 0,136,191,196, 6, 0, 0, 0, 0,248,191,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168,197,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 24,198,196, 6, 0, 0, 0, 0, 56,197,196, 6, 0, 0, 0, 0,136,191,196, 6, 0, 0, 0, 0,104,192,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24,198,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,136,198,196, 6, 0, 0, 0, 0,168,197,196, 6, 0, 0, 0, 0,104,192,196, 6, 0, 0, 0, 0,216,192,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136,198,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,248,198,196, 6, 0, 0, 0, 0, 24,198,196, 6, 0, 0, 0, 0, 24,191,196, 6, 0, 0, 0, 0, 72,193,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248,198,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,104,199,196, 6, 0, 0, 0, 0,136,198,196, 6, 0, 0, 0, 0,216,192,196, 6, 0, 0, 0, 0, 72,193,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104,199,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,216,199,196, 6, 0, 0, 0, 0,248,198,196, 6, 0, 0, 0, 0,200,189,196, 6, 0, 0, 0, 0,104,192,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,199,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 72,200,196, 6, 0, 0, 0, 0,104,199,196, 6, 0, 0, 0, 0,200,189,196, 6, 0, 0, 0, 0, 72,193,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72,200,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,184,200,196, 6, 0, 0, 0, 0,216,199,196, 6, 0, 0, 0, 0,248,191,196, 6, 0, 0, 0, 0,184,193,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184,200,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 40,201,196, 6, 0, 0, 0, 0, 72,200,196, 6, 0, 0, 0, 0, 24,191,196, 6, 0, 0, 0, 0,184,193,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,201,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,152,201,196, 6, 0, 0, 0, 0,184,200,196, 6, 0, 0, 0, 0,216,192,196, 6, 0, 0, 0, 0,184,193,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,152,201,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 8,202,196, 6, 0, 0, 0, 0, 40,201,196, 6, 0, 0, 0, 0, 40,194,196, 6, 0, 0, 0, 0,152,194,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8,202,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,120,202,196, 6, 0, 0, 0, 0,152,201,196, 6, 0, 0, 0, 0,248,191,196, 6, 0, 0, 0, 0,152,194,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120,202,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,232,202,196, 6, 0, 0, 0, 0, 8,202,196, 6, 0, 0, 0, 0,184,193,196, 6, 0, 0, 0, 0, 40,194,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232,202,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 88,203,196, 6, 0, 0, 0, 0,120,202,196, 6, 0, 0, 0, 0,104,192,196, 6, 0, 0, 0, 0, 8,195,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88,203,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,200,203,196, 6, 0, 0, 0, 0,232,202,196, 6, 0, 0, 0, 0, 40,194,196, 6, 0, 0, 0, 0, 8,195,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,203,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 56,204,196, 6, 0, 0, 0, 0, 88,203,196, 6, 0, 0, 0, 0,136,191,196, 6, 0, 0, 0, 0,120,195,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,204,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0,168,204,196, 6, 0, 0, 0, 0,200,203,196, 6, 0, 0, 0, 0,152,194,196, 6, 0, 0, 0, 0,120,195,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168,204,196, 6, 0, 0, 0, 0,212, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,204,196, 6, 0, 0, 0, 0, 8,195,196, 6, 0, 0, 0, 0,120,195,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 24,205,196, 6, 0, 0, 0, 0,214, 0, 0, 0, + 1, 0, 0, 0,232,208,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,191,196, 6, 0, 0, 0, 0, 56,190,196, 6, + 0, 0, 0, 0,168,190,196, 6, 0, 0, 0, 0,248,191,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +126, 7, 0, 0,235, 3, 0, 0, 5, 4, 0, 0, 7, 7,127, 7, 27, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,248, 11,197, 6, 0, 0, 0, 0,248, 11,197, 6, 0, 0, 0, 0, 8,206,196, 6, 0, 0, 0, 0,120,207,196, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8,206,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,120,207,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,148, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, + 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, + 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, + 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +126, 7, 0, 0,235, 3, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,168,111,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216,158,217, 3, - 0, 0, 0, 0,248,109,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 67, 0, 0,125,195, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 75, 67, 1, 0,125,195, 0, 0, 0, 0,203, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0,252, 0, 0, 0, 0, 0, 0, 0, -202, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0,252, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,120,207,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8,206,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,109, 69, 0, 0,128,192, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,238, 68, 0, 0, 0, 0, 0, 0, 0, 64,112, 7, 0, 0,129, 7, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, +111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 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,128, 63, 0, 0,128, 63, 2, 0, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, + 10, 0,129, 7, 2, 0,112, 7, 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, 5, 4, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 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, 68, 65, 84, 65,160, 0, 0, 0,232,208,196, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,120,233,196, 6, + 0, 0, 0, 0, 24,205,196, 6, 0, 0, 0, 0, 72,193,196, 6, 0, 0, 0, 0,216,192,196, 6, 0, 0, 0, 0,184,193,196, 6, + 0, 0, 0, 0, 24,191,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, +139, 1, 0, 0, 4, 4, 94, 1,140, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,232,196, 6, + 0, 0, 0, 0, 56,232,196, 6, 0, 0, 0, 0,216,209,196, 6, 0, 0, 0, 0, 72,211,196, 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, 68, 65, 84, 65, + 40, 1, 0, 0,216,209,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 72,211,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,175, 67, 0, 0, 0, 0, + 0, 0,208, 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, 93, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,174, 67, 0, 0,200, 65, 0,128,174, 67, + 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 94, 1, 26, 0, 94, 1, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0,114, 1, 0, 0, +139, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, + 40, 1, 0, 0, 72,211,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,209,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0,128,174, 67, 0, 0, 61,196, 0, 0, 0, 0, 0, 0, 0, 0,255,127,166, 67,255,255,184,195, + 0, 0, 0, 0, 77, 1, 0, 0, 94, 1, 0, 0, 0, 0, 0, 0,113, 1, 0, 0, 0, 0, 0, 0, 78, 1, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 0, 0,113, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0, 94, 1,114, 1, 77, 1, +114, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, +113, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 1,114, 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,184,212,196, 6, 0, 0, 0, 0,152,230,196, 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, 68, 65, 84, 65, + 88, 1, 0, 0,184,212,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 88,214,196, 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, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99, +111,110,116,101,120,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, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99, +111,110,116,101,120,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, 67,111,110,116,101,120,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,220,255, 76, 1, 36, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 88,214,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,248,215,196, 6, 0, 0, 0, 0,184,212,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,135,255, 76, 1, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0,248,215,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,152,217,196, 6, 0, 0, 0, 0, 88,214,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97, +121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97, +121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,255, 76, 1, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,152,217,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 56,219,196, 6, 0, 0, 0, 0,248,215,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,140,254, 76, 1,203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 88, 1, 0, 0, 56,219,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,216,220,196, 6, 0, 0, 0, 0,152,217,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110, +116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110, +116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,110,116,105, 45, 65,108,105, 97,115,105,110, +103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58,254, 76, 1, 58, 0, 20, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,216,220,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,120,222,196, 6, 0, 0, 0, 0, 56,219,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 97,109,112,108,101,100, 32, 77,111,116,105,111,110, 32, 66,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 34,254, 76, 1, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0,120,222,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 24,224,196, 6, 0, 0, 0, 0,216,220,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, + 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, + 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,104, 97,100,105,110,103, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,254, 76, 1, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 24,224,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,184,225,196, 6, 0, 0, 0, 0,120,222,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,242,253, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0,184,225,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 88,227,196, 6, 0, 0, 0, 0, 24,224,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111, +115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111, +115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,111,115,116, 32, 80,114,111, 99,101,115,115, +105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,218,253, 76, 1, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 88,227,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0,248,228,196, 6, 0, 0, 0, 0,184,225,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,194,253, 76, 1, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 88, 1, 0, 0,248,228,196, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,152,230,196, 6, 0, 0, 0, 0, 88,227,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117, +116,112,117,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, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117, +116,112,117,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, 79,117,116,112,117,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, 40,253, 76, 1,130, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,152,230,196, 6, 0, 0, 0, 0,213, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,228,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16,253, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, +248, 0, 0, 0, 56,232,196, 6, 0, 0, 0, 0,179, 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, 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, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 21, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,120,233,196, 6, 0, 0, 0, 0,214, 0, 0, 0, + 1, 0, 0, 0,232,240,196, 6, 0, 0, 0, 0,232,208,196, 6, 0, 0, 0, 0,200,189,196, 6, 0, 0, 0, 0,104,192,196, 6, + 0, 0, 0, 0,216,192,196, 6, 0, 0, 0, 0, 72,193,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 6, 0, 0, 0, 0, 0, 0,139, 1, 0, 0, 17, 17, 32, 6,140, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88,240,196, 6, 0, 0, 0, 0, 88,240,196, 6, 0, 0, 0, 0,104,234,196, 6, 0, 0, 0, 0,232,238,196, 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, 68, 65, 84, 65, 40, 1, 0, 0,104,234,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216,235,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, + 0, 0,196, 68, 0, 0, 0, 0, 0, 0,208, 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, 31, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,224,195, 68, + 0, 0,200, 65, 0,224,195, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, + 10, 0, 32, 6, 26, 0, 32, 6, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 6, 26, 0, + 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,216,235,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,232,238,196, 6, + 0, 0, 0, 0,104,234,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 67, 0, 0,185,195, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 75, 67, 0, 0,185,195, 0, 0, 0, 0,203, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0,113, 1, 0, 0, 0, 0, 0, 0, +202, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0,113, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, - 6, 0,220, 0,253, 0,203, 0,253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 4, 0, 0, -240, 4, 0, 0, 95, 0, 0, 0, 91, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,253, 0, - 0, 0, 4, 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, + 6, 0,220, 0,114, 1,203, 0,114, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +219, 0, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,114, 1, + 0, 0, 4, 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, 72,237,196, 6, 0, 0, 0, 0, 72,237,196, 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, 68, 65, 84, 65, 88, 1, 0, 0, 72,237,196, 6, 0, 0, 0, 0,213, 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, 76, 79, 71, 73, + 67, 95, 80, 84, 95,112,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 79, 71, 73, + 67, 95, 80, 84, 95,112,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,114,111,112, +101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,196,255, +203, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,216,158,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,136,160,217, 3, - 0, 0, 0, 0,168,111,217, 3, 0, 0, 0, 0, 0, 0,112,196, 0, 0,112, 68, 0, 0, 7,196, 0, 0, 7, 68, 0, 0,112,196, - 0, 0,112, 68, 0, 0, 7,196, 0, 0, 7, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,128, 59, 70, 0,128, 59, 70,172,197, 39, 55, 0, 80,195, 71, 0, 0, 0, 0, 0, 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, - 20, 4, 0, 0, 91, 1, 0, 0, 91, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 0, 0, 7, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,232,238,196, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,235,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,160, 68, 0, 0, 0, 0, 0, 0,112, 67, 0, 80, 31,195, 0,234,179, 68,224,198,182,194,184,177,165, 67, 51, 5, 0, 0, + 68, 5, 0, 0, 18, 0, 0, 0,113, 1, 0, 0, 0, 0, 0, 0, 50, 5, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, + 50, 5, 0, 0, 18, 0, 0, 0,113, 1, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,250, 70, 0, 0,250, 70, 0, 0, 0, 63, + 72,225,154, 63, 10, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 68, 5,114, 1, 51, 5, 96, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0, 0, 0, 31, 6, 0, 0, 26, 0, 0, 0,139, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 5,114, 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, 68, 65, 84, 65, 40, 1, 0, 0,136,160,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,216,158,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, - 0, 0,122, 67, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0,252, 0, 0, 0, 18, 0, 0, 0, - 20, 4, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 20, 4, 0, 0, 18, 0, 0, 0,252, 0, 0, 0, 0, 0, 32, 65, - 0, 0, 0, 63, 0,124,146, 72, 0, 0, 0, 66, 10,215, 35, 60, 0, 0,200, 66,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, - 8, 0, 21, 4,253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 20, 4, 0, 0, 95, 0, 0, 0, 91, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 4,253, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 72, 0, 0, 0, 88,240,196, 6, + 0, 0, 0, 0,192, 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, 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,255, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,232,240,196, 6, + 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,168,247,196, 6, 0, 0, 0, 0,120,233,196, 6, 0, 0, 0, 0, 40,194,196, 6, + 0, 0, 0, 0,152,194,196, 6, 0, 0, 0, 0,248,191,196, 6, 0, 0, 0, 0,184,193,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 65, 5, 0, 0,126, 7, 0, 0,141, 1, 0, 0,233, 3, 0, 0, 9, 9, 62, 2, 93, 2, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,244,196, 6, 0, 0, 0, 0,184,244,196, 6, 0, 0, 0, 0,216,241,196, 6, + 0, 0, 0, 0, 72,243,196, 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, 68, 65, 84, 65, 40, 1, 0, 0,216,241,196, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 72,243,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230, 67, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0,128, 15, 68, 0, 0, 0, 0, 0, 0,208, 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, 61, 2, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0, 64, 15, 68, 0, 0,200, 65, 0, 64, 15, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 62, 2, 26, 0, 62, 2, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 65, 5, 0, 0,126, 7, 0, 0,141, 1, 0, 0,166, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 62, 2, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72,243,196, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,241,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,181, 67, 0, 0, 0, 0, + 0,128,218, 67, 0, 0, 0, 0,131,248, 1, 68, 0, 0, 0, 0, 86, 26, 3, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 2, 0, 0, 0, 0, 0, 0, + 66, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,215, 35, 60, 0, 0,122, 68, 0, 0, 0, 0, + 1, 0, 3, 0, 0, 0, 0, 4, 10, 0, 62, 2, 67, 2, 62, 2, 67, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 65, 5, 0, 0,126, 7, 0, 0,167, 1, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 62, 2, 67, 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, 68, 65, 84, 65,240, 0, 0, 0,120,150,199, 3, 0, 0, 0, 0,180, 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, 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, 68, 65, 84, 65,160, 2, 0, 0,184,244,196, 6, 0, 0, 0, 0,186, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 64, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,152, 37,215, 3, 0, 0, 0, 0,214, 0, 0, 0, - 1, 0, 0, 0,184, 38,215, 3, 0, 0, 0, 0,120, 36,215, 3, 0, 0, 0, 0, 72, 65,201, 3, 0, 0, 0, 0, 40, 62,201, 3, - 0, 0, 0, 0,168, 64,201, 3, 0, 0, 0, 0,232, 65,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 47, 2, 0, 0, 93, 1, 0, 0,194, 2, 0, 0, 2, 2, 48, 2,102, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,232,151,199, 3, 0, 0, 0, 0,232,151,199, 3, 0, 0, 0, 0, 56,162,217, 3, 0, 0, 0, 0, 72,167,217, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56,162,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,232,163,217, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 89, 68, 0, 0, 0, 0, 0, 0,208, 65,154,216, 65, 55, - 0, 0, 12, 68, 0, 0, 0, 0, 0, 0,208, 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, 47, 2, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192, 11, 68, - 0, 0,200, 65, 0,192, 11, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, - 10, 0, 48, 2, 26, 0, 48, 2, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 47, 2, 0, 0, 93, 1, 0, 0,118, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 2, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,168,247,196, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 56, 5,197, 6, + 0, 0, 0, 0,232,240,196, 6, 0, 0, 0, 0, 8,195,196, 6, 0, 0, 0, 0,120,195,196, 6, 0, 0, 0, 0,152,194,196, 6, + 0, 0, 0, 0, 40,194,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 63, 5, 0, 0,141, 1, 0, 0, +233, 3, 0, 0, 1, 1,251, 3, 93, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 3,197, 6, + 0, 0, 0, 0,136, 3,197, 6, 0, 0, 0, 0,152,248,196, 6, 0, 0, 0, 0, 88,254,196, 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, 68, 65, 84, 65, + 40, 1, 0, 0,152,248,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 8,250,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,113, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,192,126, 68, 0, 0, 0, 0, + 0, 0,208, 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,250, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,126, 68, 0, 0,200, 65, 0,128,126, 68, + 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,251, 3, 26, 0,251, 3, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 63, 5, 0, 0,141, 1, 0, 0, +166, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,251, 3, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, + 40, 1, 0, 0, 8,250,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,120,251,196, 6, 0, 0, 0, 0,152,248,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 64, 70,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67,255,127, 70,196, + 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0, 44, 3,143, 0, + 26, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0,167, 1, 0, 0, +233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 67, 2, 0, 0, 5, 0, 3, 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, 68, 65, 84, 65, + 40, 1, 0, 0,120,251,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,232,252,196, 6, 0, 0, 0, 0, 8,250,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 67, 0, 0,206,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, 0, 0,206,194, + 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0, +102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 63, 5, 0, 0,167, 1, 0, 0, +167, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 6, 0, 34, 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, 68, 65, 84, 65, + 40, 1, 0, 0,232,252,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 88,254,196, 6, 0, 0, 0, 0,120,251,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 67, 0, 0,109,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0, 0,109,196, + 0,128,145,195,163, 0, 0, 0,180, 0, 0, 0, 0, 0, 0, 0,144, 2, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0,144, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,180, 0,145, 2,163, 0, +145, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 5, 0, 0, 63, 5, 0, 0,167, 1, 0, 0, +233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, + 40, 1, 0, 0, 88,254,196, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,252,196, 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, 69, 1, 0, 0, 63, 5, 0, 0,167, 1, 0, 0, +233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,251, 3, 67, 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,200,255,196, 6, 0, 0, 0, 0, 68, 65, 84, 65, +112, 3, 0, 0,200,255,196, 6, 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0,190, 35, 30, 61, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 75, 40,139, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187, + 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,190, 35, 30, 61, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 75, 40,139, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,149, 53,207, 65, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,112,121,107, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,249,195, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,190, 35, 30, 61, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 75, 40,139, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,207, 3,116, 64, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,207, 3,116, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,207, 3,116, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,149, 53,207, 65,214,211,111, 65, 0, 0, 0, 0, 0, 0, 0, 0,221, 57, 80, 61, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,160, 65, 0, 0, 5, 0,251,251, 0, 0, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, 3,236,234,190, + 1, 0, 0, 0, 0, 0,128, 63, 0, 0,180, 66, 0, 0,180, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 96, 1, 0, 0,136, 3,197, 6, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, + 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32, 65,205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200, 67,198, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, 8, 8,128, 0, + 0, 0, 12, 66, 0, 0,128, 63,205,204,204, 61, 0, 0,122, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 10, 0, 7, 1, 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, 68, 65, 84, 65, +160, 0, 0, 0, 56, 5,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,247,196, 6, + 0, 0, 0, 0,104,192,196, 6, 0, 0, 0, 0,136,191,196, 6, 0, 0, 0, 0,120,195,196, 6, 0, 0, 0, 0, 8,195,196, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 1, 0, 0,141, 1, 0, 0,233, 3, 0, 0, 3, 3, 68, 1, + 93, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9,197, 6, 0, 0, 0, 0, 8, 9,197, 6, + 0, 0, 0, 0, 40, 6,197, 6, 0, 0, 0, 0,152, 7,197, 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, 68, 65, 84, 65, 40, 1, 0, 0, 40, 6,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,152, 7,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,128,244, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,162, 67, 0, 0, 0, 0, 0, 0,208, 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, + 67, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,161, 67, 0, 0,200, 65, 0,128,161, 67, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 68, 1, 26, 0, 68, 1, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 1, 0, 0,141, 1, 0, 0,166, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,152, 7,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 6,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0,128,141, 67, 0, 0,244,194, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,153, 67, 0, 64, 12,196, 0, 0, 0, 0, 51, 1, 0, 0, + 68, 1, 0, 0, 18, 0, 0, 0, 66, 2, 0, 0, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, + 50, 1, 0, 0, 18, 0, 0, 0, 66, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 18, 6, 0, 0, 2, 0, 3, 3, 0, 0, 12, 4, 6, 0, 68, 1, 67, 2, 51, 1, 49, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 1, 0, 0,167, 1, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 1, 67, 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, 68, 65, 84, 65, 24, 1, 0, 0, 8, 9,197, 6, + 0, 0, 0, 0,183, 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, 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,104, 10,197, 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, + 1, 0, 0, 0, 68, 65, 84, 65, 16, 0, 0, 0,104, 10,197, 6, 0, 0, 0, 0,237, 0, 0, 0, 1, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0,200, 10,197, 6, 0, 0, 0, 0, 68, 65, 84, 65,224, 0, 0, 0,200, 10,197, 6, 0, 0, 0, 0,236, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 19, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, + 0, 0, 0, 0, 20, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 21, 0, 1, 0, 1, 0, 0, 0,104, 38,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,248, 64,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,104, 74,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8,129,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 72, 88,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 88,110,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,168, 81,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 56, 60,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,200, 67,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 40, 59,198, 6, 0, 0, 0, 0, 21, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, + 0, 0, 0, 0, 83, 78, 0, 0, 8, 1, 0, 0,136, 12,197, 6, 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0,136, 95,197, 6, + 0, 0, 0, 0,120,188,196, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 77,111, +118,105,101, 32, 84,114, 97, 99,107,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 13,197, 6, 0, 0, 0, 0,168, 18,197, 6, + 0, 0, 0, 0, 24, 19,197, 6, 0, 0, 0, 0,136, 26,197, 6, 0, 0, 0, 0,248, 26,197, 6, 0, 0, 0, 0, 56, 75,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 32,123,114, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,216, 13,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 14,197, 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, 68, 65, 84, 65, + 32, 0, 0, 0, 72, 14,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,184, 14,197, 6, 0, 0, 0, 0,216, 13,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,146, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,184, 14,197, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40, 15,197, 6, 0, 0, 0, 0, 72, 14,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,126, 7,146, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 40, 15,197, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,152, 15,197, 6, 0, 0, 0, 0,184, 14,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,152, 15,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8, 16,197, 6, + 0, 0, 0, 0, 40, 15,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 4, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0, 8, 16,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,120, 16,197, 6, 0, 0, 0, 0,152, 15,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,104, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,120, 16,197, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232, 16,197, 6, 0, 0, 0, 0, 8, 16,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,124, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,232, 16,197, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0, 88, 17,197, 6, 0, 0, 0, 0,120, 16,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,124, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 88, 17,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200, 17,197, 6, + 0, 0, 0, 0,232, 16,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 3, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,200, 17,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 56, 18,197, 6, 0, 0, 0, 0, 88, 17,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,168, 3, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 56, 18,197, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,168, 18,197, 6, 0, 0, 0, 0,200, 17,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,168, 3,168, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,168, 18,197, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 18,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 3,104, 4, + 1, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24, 19,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136, 19,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 14,197, 6, 0, 0, 0, 0,184, 14,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136, 19,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248, 19,197, 6, + 0, 0, 0, 0, 24, 19,197, 6, 0, 0, 0, 0, 72, 14,197, 6, 0, 0, 0, 0,152, 15,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248, 19,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104, 20,197, 6, + 0, 0, 0, 0,136, 19,197, 6, 0, 0, 0, 0,184, 14,197, 6, 0, 0, 0, 0, 8, 16,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104, 20,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216, 20,197, 6, + 0, 0, 0, 0,248, 19,197, 6, 0, 0, 0, 0,152, 15,197, 6, 0, 0, 0, 0, 8, 16,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216, 20,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72, 21,197, 6, + 0, 0, 0, 0,104, 20,197, 6, 0, 0, 0, 0,216, 13,197, 6, 0, 0, 0, 0, 40, 15,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72, 21,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184, 21,197, 6, + 0, 0, 0, 0,216, 20,197, 6, 0, 0, 0, 0,216, 13,197, 6, 0, 0, 0, 0,120, 16,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184, 21,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40, 22,197, 6, + 0, 0, 0, 0, 72, 21,197, 6, 0, 0, 0, 0, 40, 15,197, 6, 0, 0, 0, 0,232, 16,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40, 22,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152, 22,197, 6, + 0, 0, 0, 0,184, 21,197, 6, 0, 0, 0, 0,120, 16,197, 6, 0, 0, 0, 0,232, 16,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,152, 22,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8, 23,197, 6, + 0, 0, 0, 0, 40, 22,197, 6, 0, 0, 0, 0,120, 16,197, 6, 0, 0, 0, 0, 88, 17,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8, 23,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120, 23,197, 6, + 0, 0, 0, 0,152, 22,197, 6, 0, 0, 0, 0,152, 15,197, 6, 0, 0, 0, 0, 88, 17,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120, 23,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232, 23,197, 6, + 0, 0, 0, 0, 8, 23,197, 6, 0, 0, 0, 0, 8, 16,197, 6, 0, 0, 0, 0,200, 17,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232, 23,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88, 24,197, 6, + 0, 0, 0, 0,120, 23,197, 6, 0, 0, 0, 0,232, 16,197, 6, 0, 0, 0, 0,200, 17,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88, 24,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200, 24,197, 6, + 0, 0, 0, 0,232, 23,197, 6, 0, 0, 0, 0, 88, 17,197, 6, 0, 0, 0, 0,200, 17,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200, 24,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56, 25,197, 6, + 0, 0, 0, 0, 88, 24,197, 6, 0, 0, 0, 0, 88, 17,197, 6, 0, 0, 0, 0, 56, 18,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56, 25,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168, 25,197, 6, + 0, 0, 0, 0,200, 24,197, 6, 0, 0, 0, 0,200, 17,197, 6, 0, 0, 0, 0, 56, 18,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168, 25,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24, 26,197, 6, + 0, 0, 0, 0, 56, 25,197, 6, 0, 0, 0, 0,152, 15,197, 6, 0, 0, 0, 0,168, 18,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24, 26,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136, 26,197, 6, + 0, 0, 0, 0,168, 25,197, 6, 0, 0, 0, 0, 8, 16,197, 6, 0, 0, 0, 0,168, 18,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136, 26,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 26,197, 6, 0, 0, 0, 0, 56, 18,197, 6, 0, 0, 0, 0,168, 18,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,248, 26,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,200, 30,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 15,197, 6, 0, 0, 0, 0, 72, 14,197, 6, 0, 0, 0, 0,184, 14,197, 6, + 0, 0, 0, 0, 8, 16,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,105, 4, 0, 0, +146, 4, 0, 0, 7, 7,127, 7, 42, 0, 1, 0, 0, 0, 0, 0, 7, 0, 8, 0, 8, 77,163, 6, 0, 0, 0, 0,248, 94,197, 6, + 0, 0, 0, 0,248, 94,197, 6, 0, 0, 0, 0,232, 27,197, 6, 0, 0, 0, 0, 88, 29,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,233, 42, 0, 73,127, 0, 0,104,217,224, 0, 73,127, 0, 0, 68, 65, 84, 65, + 40, 1, 0, 0,232, 27,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 88, 29,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,163, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, + 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, + 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,105, 4, 0, 0, +130, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 79,163, 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, 68, 65, 84, 65, + 40, 1, 0, 0, 88, 29,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232, 27,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0,192,239, 68, 0, 0, 0, 0, 0, 0, 48, 65, 0, 0, 0, 0, 1,192,237, 68, 0, 0, 0, 0, + 0, 0,128, 65,110, 7, 0, 0,127, 7, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,109, 7, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 2, 2, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,127, 7, 16, 0,110, 7, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,131, 4, 0, 0, +146, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 78,163, 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, 68, 65, 84, 65, +160, 0, 0, 0,200, 30,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,184, 35,197, 6, 0, 0, 0, 0,248, 26,197, 6, + 0, 0, 0, 0,216, 13,197, 6, 0, 0, 0, 0,120, 16,197, 6, 0, 0, 0, 0,232, 16,197, 6, 0, 0, 0, 0, 40, 15,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0,123, 0, 0, 0, 15, 15,127, 7, +124, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 28,163, 6, 0, 0, 0, 0,152, 34,197, 6, 0, 0, 0, 0,152, 34,197, 6, + 0, 0, 0, 0,184, 31,197, 6, 0, 0, 0, 0, 40, 33,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24,113,223, 0, 73,127, 0, 0,216,229, 12, 0, 73,127, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,184, 31,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 40, 33,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 96,146, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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, +126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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,136, 30,163, 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, 68, 65, 84, 65, 40, 1, 0, 0, 40, 33,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184, 31,197, 6, 0, 0, 0, 0, 0, 0, 64,192, + 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 72, 66, 88,218,103,194, 40,147,141, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +126, 7, 0, 0, 18, 0, 0, 0, 97, 0, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, + 0, 0, 32, 65, 72, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 4, 8, 0,127, 7, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 26, 0, 0, 0,123, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 29,163, 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, 68, 65, 84, 65,208, 0, 0, 0,152, 34,197, 6, + 0, 0, 0, 0,190, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 0, 0, 0, 68, 65, 84, 65, +160, 0, 0, 0,184, 35,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,120, 55,197, 6, 0, 0, 0, 0,200, 30,197, 6, + 0, 0, 0, 0,120, 16,197, 6, 0, 0, 0, 0, 88, 17,197, 6, 0, 0, 0, 0,200, 17,197, 6, 0, 0, 0, 0,232, 16,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,125, 0, 0, 0,167, 3, 0, 0, 20, 20,127, 7, + 43, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,130,163, 6, 0, 0, 0, 0,248, 49,197, 6, 0, 0, 0, 0, 88, 54,197, 6, + 0, 0, 0, 0,168, 36,197, 6, 0, 0, 0, 0,136, 48,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 56,240, 12, 0, 73,127, 0, 0,168,253, 12, 0, 73,127, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,168, 36,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 24, 38,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,229, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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, +126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 0, 0, 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,125, 0, 0, 0,150, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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,216,138,163, 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, 68, 65, 84, 65, 40, 1, 0, 0, 24, 38,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,136, 39,197, 6, 0, 0, 0, 0,168, 36,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0,128,178, 67, 0, 64, 38,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 64, 38,196, 0, 0, 0, 0,143, 0, 0, 0, +160, 0, 0, 0, 0, 0, 0, 0,152, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +142, 0, 0, 0, 0, 0, 0, 0,152, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,153, 2,143, 0,153, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0, 15, 1, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0,153, 2, 0, 0, 5, 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,152,135,163, 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, 68, 65, 84, 65, 40, 1, 0, 0,136, 39,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,152, 42,197, 6, 0, 0, 0, 0, 24, 38,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0,128,178, 67, 0, 0,240,194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 0,240,194, 0, 0, 0, 0,143, 0, 0, 0, +160, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +142, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0,120, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0,151, 0, 0, 0, 14, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0,120, 0, 0, 0, 6, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,136,163, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,248, 40,197, 6, 0, 0, 0, 0,248, 40,197, 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, 68, 65, 84, 65, 88, 1, 0, 0,248, 40,197, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,137,163, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 76, 73, 80, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111, +114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 76, 73, 80, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111, +114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79,112,101,114, 97,116,111,114, 0,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,255,143, 0, 16, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 40, 1, 0, 0,152, 42,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,168, 45,197, 6, + 0, 0, 0, 0,136, 39,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0, 64, 68,196, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15, 67, 0, 64, 68,196, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 16, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 16, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, + 6, 0,160, 0, 17, 3,143, 0, 17, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,223, 6, 0, 0, +126, 7, 0, 0,151, 0, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 17, 3, + 0, 0, 4, 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, 72,133,163, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 44,197, 6, 0, 0, 0, 0, 8, 44,197, 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, 68, 65, 84, 65, 88, 1, 0, 0, 8, 44,197, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,134,163, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 76, 73, 80, + 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 76, 73, 80, + 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71,114,101, 97, +115,101, 32, 80,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,255, +143, 0, 0, 0, 0, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0,168, 45,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 24, 47,197, 6, 0, 0, 0, 0,152, 42,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15, 67, 0, 64,116,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 67, 0,192,111,196, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +159, 0, 0, 0, 18, 0, 0, 0,208, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 8, 0, 0, 0, 2, 0, 3, 3, 0, 0, 2, 0, 6, 0,160, 0,209, 3,160, 0,191, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 0, 0,160, 0, 0, 0,151, 0, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,139,163, 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, 68, 65, 84, 65, 40, 1, 0, 0, 24, 47,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,136, 48,197, 6, 0, 0, 0, 0,168, 45,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,122, 67, 0, 0, 32,193, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 32,193, 0, 0, 32, 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,128, 0, 0, 0,128, 0, 0,124,146, 72,255,255,127,127, 0, 0, 0, 0, + 0, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 0, 0,160, 0, 0, 0,151, 0, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,132,163, 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, 68, 65, 84, 65, 40, 1, 0, 0,136, 48,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 47,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255, 0, 0,128,127, 0, 0,128,255, 0, 0,128,127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 6, 0, 0, 0, 0, 0, 0, 17, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,215, 35, 60, + 0, 0,122, 68, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 4, 10, 0, 63, 6, 17, 3, 63, 6, 17, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 0, 0,222, 6, 0, 0,151, 0, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 6, 17, 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,104,131,163, 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, 68, 65, 84, 65, 48, 1, 0, 0,248, 49,197, 6, + 0, 0, 0, 0,196, 0, 0, 0, 1, 0, 0, 0, 88, 54,197, 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, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,120, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17,200, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 40, 1, 0, 0,120, 51,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,232, 52,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,146, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, + 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, + 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,125, 0, 0, 0, +150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, + 40, 1, 0, 0,232, 52,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 51,197, 6, + 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 72, 66, 88,218,103,194, 40,147,141, 67, 0, 0, 0, 0, + 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 18, 0, 0, 0,208, 3, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, + 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, 72, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 4, 8, 0,127, 7,209, 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,126, 7, 0, 0,151, 0, 0, 0, +103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7,209, 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, 68, 65, 84, 65, +208, 0, 0, 0, 88, 54,197, 6, 0, 0, 0, 0,190, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 49,197, 6, + 0, 0, 0, 0,120, 51,197, 6, 0, 0, 0, 0,232, 52,197, 6, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 0, 0, + 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,120, 55,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 56, 75,197, 6, + 0, 0, 0, 0,184, 35,197, 6, 0, 0, 0, 0, 56, 18,197, 6, 0, 0, 0, 0,168, 18,197, 6, 0, 0, 0, 0, 8, 16,197, 6, + 0, 0, 0, 0,200, 17,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,169, 3, 0, 0,126, 7, 0, 0,169, 3, 0, 0, +103, 4, 0, 0, 20, 20,214, 3,191, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,130,163, 6, 0, 0, 0, 0,184, 69,197, 6, + 0, 0, 0, 0, 24, 74,197, 6, 0, 0, 0, 0,104, 56,197, 6, 0, 0, 0, 0, 72, 68,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,254, 12, 0, 73,127, 0, 0,200, 20, 13, 0, 73,127, 0, 0, 68, 65, 84, 65, + 40, 1, 0, 0,104, 56,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216, 57,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,212, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,128,117, 68, 0, 0, 0, 0, + 0, 0,208, 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,213, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 64,117, 68, 0, 0,200, 65, 0, 64,117, 68, + 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 0, 0, 10, 0,214, 3, 26, 0,214, 3, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,169, 3, 0, 0,126, 7, 0, 0,169, 3, 0, 0, +194, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,214, 3, 26, 0, 0, 0, 1, 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,216,138,163, 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, 68, 65, 84, 65, + 40, 1, 0, 0,216, 57,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 72, 59,197, 6, 0, 0, 0, 0,104, 56,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0, 0, 52,194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 0, 52,194, + 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0, 45, 0,143, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,169, 3, 0, 0,169, 3, 0, 0,195, 3, 0, 0, +103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 5, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,135,163, 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, 68, 65, 84, 65, + 40, 1, 0, 0, 72, 59,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 88, 62,197, 6, 0, 0, 0, 0,216, 57,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0, 0,240,194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 0,240,194, + 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0,120, 0,143, 0, +120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,169, 3, 0, 0,169, 3, 0, 0,195, 3, 0, 0, +103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 6, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,136,163, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184, 60,197, 6, 0, 0, 0, 0,184, 60,197, 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, 68, 65, 84, 65, + 88, 1, 0, 0,184, 60,197, 6, 0, 0, 0, 0,213, 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, 67, 76, 73, 80, 95, 80, 84, 95,108, 97,115,116, + 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 76, 73, 80, 95, 80, 84, 95,108, 97,115,116, + 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 32, 83, 99,114,101,101,110, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,255,143, 0, 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 88, 62,197, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,104, 65,197, 6, 0, 0, 0, 0, 72, 59,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0, 0, 37,195, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 0, 37,195, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, +164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, +164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, + 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0,165, 0,143, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,169, 3, 0, 0,169, 3, 0, 0,195, 3, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 72,133,163, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 63,197, 6, + 0, 0, 0, 0,200, 63,197, 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, 68, 65, 84, 65, 88, 1, 0, 0,200, 63,197, 6, 0, 0, 0, 0,213, 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, 67, 76, 73, 80, 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 67, 76, 73, 80, 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 71,114,101, 97,115,101, 32, 80,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,232,255,143, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, + 40, 1, 0, 0,104, 65,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216, 66,197, 6, 0, 0, 0, 0, 88, 62,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 0, 37,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 67, 0, 0, 19,195, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0, 18, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 8, 4, 0, 0, 2, 0, 3, 3, 0, 0, 2, 4, 6, 0,160, 0,165, 0,160, 0, +147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,169, 3, 0, 0, 72, 4, 0, 0,195, 3, 0, 0, +103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0,165, 0, 0, 0, 2, 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,200,139,163, 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, 68, 65, 84, 65, + 40, 1, 0, 0,216, 66,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 72, 68,197, 6, 0, 0, 0, 0,104, 65,197, 6, + 0, 0, 0, 0, 0, 0, 32,193, 0,128,117, 68,171,170,126,194, 0, 0, 0, 0, 0, 0, 32,193, 0,128,117, 68, 0, 0, 19,195, + 0, 0, 0, 0, 37, 3, 0, 0, 54, 3, 0, 0, 18, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 36, 3, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 36, 3, 0, 0, 18, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124,146, 72, +255,255,127,127, 10,215, 35, 60, 0, 0, 72, 66, 74, 0, 0, 0, 0, 0, 0, 2, 16, 0, 2, 4, 4, 0, 54, 3,165, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 4, 0, 0,126, 7, 0, 0,195, 3, 0, 0, +103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 3,165, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,132,163, 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, 68, 65, 84, 65, + 40, 1, 0, 0, 72, 68,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 66,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255, 0, 0,128,127, 0, 0,128,255, + 0, 0,128,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,150, 2, 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10,215, 35, 60, 0, 0,122, 68, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 10, 0,150, 2,165, 0,150, 2, +165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,131,163, 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, 68, 65, 84, 65, + 48, 1, 0, 0,184, 69,197, 6, 0, 0, 0, 0,196, 0, 0, 0, 1, 0, 0, 0, 24, 74,197, 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, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +120, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17,200, 0, 0, 0, 0, 2, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 56, 71,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,168, 72,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,146, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, + 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, + 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, + 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +126, 7, 0, 0,125, 0, 0, 0,150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,232,163,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,152,165,217, 3, - 0, 0, 0, 0, 56,162,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 67, 0, 0,112,193, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 67, 0, 0,157,195, 0, 0, 0, 0,200, 0, 0, 0,217, 0, 0, 0, 18, 0, 0, 0, 75, 1, 0, 0, 0, 0, 0, 0, -199, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, 18, 0, 0, 0, 75, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 10, 6, 0, 0, 2, 0, 3, 3, 0, 0, 0, 4, - 6, 0,217, 0, 76, 1,200, 0, 58, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -216, 0, 0, 0,119, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,217, 0, 76, 1, - 0, 0, 2, 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, 68, 65, 84, 65, 40, 1, 0, 0,168, 72,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 71,197, 6, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 72, 66, 88,218,103,194, + 40,147,141, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +126, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 18, 0, 0, 0,208, 3, 0, 0, 0, 0,128, 63, + 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, 72, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 4, + 8, 0,127, 7,209, 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, +126, 7, 0, 0,151, 0, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7,209, 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, 68, 65, 84, 65,208, 0, 0, 0, 24, 74,197, 6, 0, 0, 0, 0,190, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,184, 69,197, 6, 0, 0, 0, 0, 56, 71,197, 6, 0, 0, 0, 0,168, 72,197, 6, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 56, 75,197, 6, 0, 0, 0, 0,214, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 55,197, 6, 0, 0, 0, 0, 88, 17,197, 6, 0, 0, 0, 0,152, 15,197, 6, + 0, 0, 0, 0,168, 18,197, 6, 0, 0, 0, 0, 56, 18,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +167, 3, 0, 0,169, 3, 0, 0,103, 4, 0, 0, 20, 20,168, 3,191, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,130,163, 6, + 0, 0, 0, 0,120, 89,197, 6, 0, 0, 0, 0,216, 93,197, 6, 0, 0, 0, 0, 40, 76,197, 6, 0, 0, 0, 0, 8, 88,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 21, 13, 0, 73,127, 0, 0,120, 22, 13, 0, + 73,127, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 40, 76,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,152, 77,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,212, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, + 0, 0,106, 68, 0, 0, 0, 0, 0, 0,208, 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,167, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,105, 68, + 0, 0,200, 65, 0,192,105, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 0, 0, + 10, 0,168, 3, 26, 0,168, 3, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +167, 3, 0, 0,169, 3, 0, 0,194, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 3, 26, 0, + 0, 0, 1, 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,216,138,163, 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, 68, 65, 84, 65, 40, 1, 0, 0,152, 77,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 8, 79,197, 6, + 0, 0, 0, 0, 40, 76,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0, 0, 52,194, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15, 67, 0, 0, 52,194, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, + 6, 0,160, 0, 45, 0,143, 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,195, 3, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,135,163, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8, 79,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 24, 82,197, 6, + 0, 0, 0, 0,152, 77,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,178, 67, 0, 0,240,194, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15, 67, 0, 0,240,194, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, + 6, 0,160, 0,120, 0,143, 0,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,195, 3, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,136,163, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 80,197, 6, 0, 0, 0, 0,120, 80,197, 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, 68, 65, 84, 65, 88, 1, 0, 0,120, 80,197, 6, 0, 0, 0, 0,213, 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, 67, 76, 73, 80, + 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 76, 73, 80, + 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 32, + 83, 99,114,101,101,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,255, +143, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,152,165,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 72,167,217, 3, - 0, 0, 0, 0,232,163,217, 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, 68, 65, 84, 65, 40, 1, 0, 0, 24, 82,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 40, 85,197, 6, 0, 0, 0, 0, 8, 79,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0,128,178, 67, 0, 0, 37,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 0, 37,195, 0, 0, 0, 0,143, 0, 0, 0, +160, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +142, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0,165, 0,143, 0,165, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195, 3, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,133,163, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,136, 83,197, 6, 0, 0, 0, 0,136, 83,197, 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, 68, 65, 84, 65, 88, 1, 0, 0,136, 83,197, 6, + 0, 0, 0, 0,213, 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, 67, 76, 73, 80, 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 76, 73, 80, 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 2, 0, 0, - 47, 2, 0, 0,119, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 0, 0, 4, 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, 71,114,101, 97,115,101, 32, 80,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,255,143, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72,167,217, 3, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,152,165,217, 3, 0, 0, 0, 0, 0, 0, 16,193, 0, 0,130, 67, 0, 0,160,192, 0, 0,160, 64, 0, 0, 0, 0, - 0, 0,122, 67, 0, 0, 16,193, 0, 0, 32, 65, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 75, 1, 0, 0, 18, 0, 0, 0, - 86, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 86, 1, 0, 0, 18, 0, 0, 0, 75, 1, 0, 0,111, 18,131, 58, -111, 18,131, 58, 0,124,146, 72, 0, 80, 67, 71, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, - 0, 0, 87, 1, 76, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,217, 0, 0, 0, - 47, 2, 0, 0,119, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 1, 76, 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, 68, 65, 84, 65, 40, 1, 0, 0, 40, 85,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,152, 86,197, 6, + 0, 0, 0, 0, 24, 82,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 64,116,196, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32, 67, 0,192,111,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +159, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0, 18, 0, 0, 0,208, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 8, 0, 0, 0, 2, 0, 3, 3, 0, 0, 2, 0, + 6, 0,160, 0,209, 3,160, 0,191, 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,195, 3, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,139,163, 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, 68, 65, 84, 65,240, 0, 0, 0,232,151,199, 3, 0, 0, 0, 0,178, 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, 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, 68, 65, 84, 65, 40, 1, 0, 0,152, 86,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 8, 88,197, 6, + 0, 0, 0, 0, 40, 85,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 32,193, 0, 0, 32, 65, 0, 0, 0, 0, + 0, 0,122, 67, 0, 0, 32,193, 0, 0, 32, 65, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0,164, 0, 0, 0, 18, 0, 0, 0, +167, 3, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0,167, 3, 0, 0, 18, 0, 0, 0,164, 0, 0, 0, 0, 0,128, 0, + 0, 0,128, 0, 0,124,146, 72,255,255,127,127, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0,168, 3,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +167, 3, 0, 0,195, 3, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 3,165, 0, + 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,132,163, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8, 88,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,152, 86,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255, + 0, 0,128,127, 0, 0,128,255, 0, 0,128,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 2, 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,215, 35, 60, 0, 0,122, 68, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, + 10, 0,104, 2,165, 0,104, 2,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,131,163, 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, 68, 65, 84, 65, 48, 1, 0, 0,120, 89,197, 6, 0, 0, 0, 0,196, 0, 0, 0, 1, 0, 0, 0,216, 93,197, 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, 20, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,120, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17,200, 0, 0, + 0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,248, 90,197, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0,104, 92,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,146, 68, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,125, 0, 0, 0,150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,104, 92,197, 6, 0, 0, 0, 0,215, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 90,197, 6, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, + 0, 0, 72, 66, 88,218,103,194, 40,147,141, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 18, 0, 0, 0, +208, 3, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, 72, 0, 0, 0, + 0, 0, 0, 2, 4, 0, 0, 4, 8, 0,127, 7,209, 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,126, 7, 0, 0,151, 0, 0, 0,103, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,127, 7,209, 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, 68, 65, 84, 65,208, 0, 0, 0,216, 93,197, 6, 0, 0, 0, 0,190, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 89,197, 6, 0, 0, 0, 0,248, 90,197, 6, 0, 0, 0, 0,104, 92,197, 6, + 0, 0, 0, 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, 24,120,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, - 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,112, 0, 0, 0, 24,120,214, 3, 0, 0, 0, 0, 37, 1, 0, 0, - 1, 0, 0, 0,168,194,217, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,184, 38,215, 3, - 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 37,215, 3, 0, 0, 0, 0,232, 65,201, 3, - 0, 0, 0, 0,168, 64,201, 3, 0, 0, 0, 0,200, 62,201, 3, 0, 0, 0, 0,104, 63,201, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 49, 2, 0, 0,240, 4, 0, 0, 93, 1, 0, 0,194, 2, 0, 0, 8, 8,192, 2,102, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,153,199, 3, 0, 0, 0, 0, 88,153,199, 3, 0, 0, 0, 0,248,168,217, 3, - 0, 0, 0, 0, 8,174,217, 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, 68, 65, 84, 65, 40, 1, 0, 0,248,168,217, 3, 0, 0, 0, 0,215, 0, 0, 0, - 1, 0, 0, 0,168,170,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,245, 67, 0, 0, 0, 0, - 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 48, 68, 0, 0, 0, 0, 0, 0,208, 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,191, 2, 0, 0, 0, 0, 0, 0, - 25, 0, 0, 0, 0,192, 47, 68, 0, 0,200, 65, 0,192, 47, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,192, 2, 26, 0,192, 2, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 49, 2, 0, 0,240, 4, 0, 0, 93, 1, 0, 0,118, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,192, 2, 26, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,168,170,217, 3, 0, 0, 0, 0,215, 0, 0, 0, - 1, 0, 0, 0, 88,172,217, 3, 0, 0, 0, 0,248,168,217, 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,240, 4, 0, 0,240, 4, 0, 0,119, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0, 88,172,217, 3, 0, 0, 0, 0,215, 0, 0, 0, - 1, 0, 0, 0, 8,174,217, 3, 0, 0, 0, 0,168,170,217, 3, 0, 0, 0, 0, 0, 0,240,195, 0, 0,240, 67, 0, 0,135,195, - 0, 0,135, 67,238, 33,143,196,238, 33,143, 68, 0, 0, 7,196, 0, 0, 7, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 2, 0, 0, 0, 0, 0, 0, - 75, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 59, 70, 0,128, 59, 70,172,197, 39, 55, 0, 80,195, 71, 0, 0, 0, 0, - 0, 0, 6, 0, 0, 0, 0, 4, 0, 0,192, 2, 76, 1,192, 2, 76, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 49, 2, 0, 0,240, 4, 0, 0,119, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,192, 2, 76, 1, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 8,174,217, 3, 0, 0, 0, 0,215, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,172,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 0, 0, - 0, 0, 0, 65, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, - 75, 1, 0, 0, 18, 0, 0, 0,201, 2, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0,201, 2, 0, 0, 18, 0, 0, 0, - 75, 1, 0, 0, 0, 0, 32, 65, 0, 0, 0, 63, 0,124,146, 72, 0, 0, 0, 66, 10,215, 35, 60, 0, 0,200, 66,105, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 0,202, 2, 76, 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, 1, 0, 1, 0, 0, 0, 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, 68, 65, 84, 65,240, 0, 0, 0, 88,153,199, 3, 0, 0, 0, 0,180, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 64, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 0, 0,216, 11, 0, 0,168,194,217, 3, - 0, 0, 0, 0,171, 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, 83, 67, 83, 99,101,110,101, 0,116, 97,103,101, 0, 97,105,110, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,173,200, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,213,217, 3, 0, 0, 0, 0, 24, 51,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 40,117,216, 3, 0, 0, 0, 0,136,118,216, 3, 0, 0, 0, 0, 40,117,216, 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, 1, 0, 0, 0, 1, 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, 8,207,217, 3, 0, 0, 0, 0,232,141,214, 15, - 0, 0, 0, 0, 17, 2, 24, 0, 90, 90, 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,192, 0, 0, 0, - 68,172, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 1, 0, 0, 0,250, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0,100, 0, 0, 0, 0, 0, 1, 0, 0, 0,128, 63, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 2,224, 1, 60, 0, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, - 6, 0, 50, 0,141, 0,128, 7, 56, 4, 8, 0, 8, 0, 24, 0, 17, 0, 0, 0, 90, 0, 1, 0, 81, 0, 0, 0, 23, 0, 33, 0, - 2, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 8, 0, 24, 0, 10, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 24,174,200, 3, 0, 0, 0, 0, 24,174,200, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 1, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 5, 0, 2, 0, - 1, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47,116,109,112, 92, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 5, 0, 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, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204, 76, 63, -205,204, 76, 63,205,204, 76, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0,128, 63, 0, 0,128, 63,173, 2, 95, 0,154,153,217, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 1, 0,180, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 76, 69, 78, - 68, 69, 82, 95, 82, 69, 78, 68, 69, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,172, 0, 0, - 0, 0,128, 63,102,166,171, 67, 0, 0,128, 63, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,209,117, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,149,158, 15, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 88, 87,171, 3, 0, 0, 0, 0, 1, 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,128, 2,224, 1, 60, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 1, 0,180, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, -205,204,204, 61,154,153,153, 62,205,204, 76, 62,219, 15, 73, 63,102,102,102, 63, 0, 0, 0, 64,154,153, 25, 63, 0, 0, 64, 65, -102,102,166, 63, 0, 0, 0, 65, 0, 0,160, 65, 6, 0, 0, 0, 0, 0,192, 64, 0, 0,128, 63, 0, 0, 0, 0,205,204, 28, 65, - 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 1, 0,128, 0, 5, 0,218, 0, 0, 0, 60, 0, 5, 0, 1, 0, 5, 0, 0, 0, 0, 0, - 0, 0, 0, 64, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195,245, 28,193, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65,128, 0, 0, 0, 24,173,200, 3, 0, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, - 40, 0, 0, 0, 40,117,216, 3, 0, 0, 0, 0,143, 0, 0, 0, 1, 0, 0, 0,216,117,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,232, 1, 20, 1,184,219,217, 3, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0,216,117,216, 3, 0, 0, 0, 0,143, 0, 0, 0, 1, 0, 0, 0,136,118,216, 3, 0, 0, 0, 0, 40,117,216, 3, - 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0,118, 2,238, 1,168,225,217, 3, 0, 0, 0, 0, 68, 65, 84, 65, - 40, 0, 0, 0,136,118,216, 3, 0, 0, 0, 0,143, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,117,216, 3, - 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0,108, 0, 86, 1,200,213,217, 3, 0, 0, 0, 0, 68, 65, 84, 65, -232, 1, 0, 0, 8,207,217, 3, 0, 0, 0, 0,167, 0, 0, 0, 1, 0, 0, 0,216,202,207, 3, 0, 0, 0, 0,152,203,207, 3, - 0, 0, 0, 0,168, 1,211, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 1, 0, 1, 0,205,204, 76, 63, - 0, 0,180, 66, 9, 0, 1, 0, 0, 0,128, 63,111, 18,131, 58,205,204,204, 61, 0, 0, 1, 0, 32, 0, 32, 0, 32, 0, 1, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,232, 10,219, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 80, 0, 0, 2, 0, 2, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 5, 0, 5, 0,255,255, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 66, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 66, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 66, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 66, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 66, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 66, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 62, 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,128, 63, 10,215, 35, 60,205,204,204, 61, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,250, 0,205,204,204, 61,205,204,204, 61,102,102,166, 63, 0, 0,192, 63, 0, 0,240, 65, - 72,225,122, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 67, 2, 0, 3, 2, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 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, 17, 0, 0, 0, - 35, 0, 0, 0,204,197,121, 63, 0, 0, 0, 63, 35, 0, 0, 0,204,197,121, 63, 0, 0, 0, 63, 17, 0, 0, 0, 68, 65, 84, 65, - 56, 0, 0, 0,216,202,207, 3, 0, 0, 0, 0,164, 0, 0, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,255,255,255,128, 1, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 0, 0, 0,152,203,207, 3, 0, 0, 0, 0,164, 0, 0, 0, - 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,200,255,128, 1, 0, 0, 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, 68, 65, 84, 65, - 96, 0, 0, 0,168, 1,211, 3, 0, 0, 0, 0,162, 0, 0, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0,120, 58,171, 3, - 0, 0, 0, 0,255,100,100,128, 1, 0, 0, 0,128, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,155, 9, 25, 67, -190, 23,237, 64, 75, 1,147, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,120, 0, 0, 0, 24,174,200, 3, - 0, 0, 0, 0,149, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100, -101,114, 76, 97,121,101,114, 0,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 15, 0, 0, 0, 0, 0,255,127, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 67, 65, 0, 0,200, 0, 0, 0, 24, 98,200, 3, 0, 0, 0, 0, 22, 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, 67, 65, 67, 97, -109,101,114, 97, 0, 97,109,101,114, 97, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, - 0, 0, 0, 63,205,204,204, 61, 0, 0,200, 66, 0, 0, 12, 66,161, 14,234, 64, 0, 0, 0, 63, 0, 0, 0, 66, 0, 0,144, 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, 76, 65, 0, 0, 16, 2, 0, 0,120,209,217, 3, 0, 0, 0, 0, 36, 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, 76, 65, 76, 97, -109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,247,255,239, 65, 0, 0,150, 66,154,153, 25, 62, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 8,212,217, 3, 0, 0, 0, 0, 2, 0, 0, 0, 46, 26,128, 63, 25, 4,240, 65, 0, 0, 52, 66, 0, 0,128, 63, - 0, 0, 64, 64,205,204, 76, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 11, 3, 0, 1, 0, 0, 0, 0, 2, 1, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,111, 18,131, 58, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 64, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,119,216, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 64, 1, 0, 0, 8,212,217, 3, 0, 0, 0, 0,119, 1, 0, 0, - 1, 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,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 2, 0, 1, 0, 0, 0,128, 67, 0, 0, 0, 0, - 0, 0,128, 63,243, 4, 53,191,242, 4, 53, 63,242, 4, 53,191,243, 4, 53, 63, 40, 67,201, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 40, 67,201, 3, 0, 0, 0, 0,117, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,119,216, 3, - 0, 0, 0, 0, 12, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 79, 0, 0, 24, 2, 0, 0, 24, 51,163, 3, - 0, 0, 0, 0,142, 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, 87, 79, 87,111,114,108,100, 0, 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, 0, 0, 1, 0, 0, 0, 83, 78, 0, 0, 8, 1, 0, 0,136, 95,197, 6, + 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0,248,174,197, 6, 0, 0, 0, 0,136, 12,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 83, 99,114,105,112,116,105,110,103, 0,103, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 99, 80, 61,114, 99, 80, 61,114, 99, 80, 61, -199, 54, 36, 60,199, 54, 36, 60,199, 54, 36, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,205,204, 28, 65, 0, 0, 0, 0, 0, 0, 32, 0, -128, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 64, 0, 0,200, 65, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0,112, 65, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0,128, 63,205,204, 76, 61, 0, 0, 5, 0, 0, 0, 0, 0, 10,215,163, 59, - 0, 0, 0, 0, 0, 0,128, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0,216, 96,197, 6, 0, 0, 0, 0,136,102,197, 6, 0, 0, 0, 0,248,102,197, 6, 0, 0, 0, 0, 40,112,197, 6, + 0, 0, 0, 0,152,112,197, 6, 0, 0, 0, 0,168,167,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 32, 0, 0, 0,216, 96,197, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72, 97,197, 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, 68, 65, 84, 65, 32, 0, 0, 0, 72, 97,197, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,184, 97,197, 6, 0, 0, 0, 0,216, 96,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,184, 97,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40, 98,197, 6, + 0, 0, 0, 0, 72, 97,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0, 40, 98,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,152, 98,197, 6, 0, 0, 0, 0,184, 97,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,152, 98,197, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8, 99,197, 6, 0, 0, 0, 0, 40, 98,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,168, 3, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8, 99,197, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0,120, 99,197, 6, 0, 0, 0, 0,152, 98,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,168, 3, + 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,120, 99,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232, 99,197, 6, + 0, 0, 0, 0, 8, 99,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 5,168, 3, 0, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,232, 99,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 88,100,197, 6, 0, 0, 0, 0,120, 99,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 5, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 88,100,197, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200,100,197, 6, 0, 0, 0, 0,232, 99,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,104, 1, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,200,100,197, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0, 56,101,197, 6, 0, 0, 0, 0, 88,100,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 5,104, 1, + 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 56,101,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,168,101,197, 6, + 0, 0, 0, 0,200,100,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 2,104, 1, 1, 0, 0, 0, 68, 65, 84, 65, + 32, 0, 0, 0,168,101,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 24,102,197, 6, 0, 0, 0, 0, 56,101,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 5,236, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 24,102,197, 6, + 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,136,102,197, 6, 0, 0, 0, 0,168,101,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,126, 7,236, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,136,102,197, 6, 0, 0, 0, 0,211, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,102,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 2,168, 3, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248,102,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104,103,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 97,197, 6, 0, 0, 0, 0,184, 97,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104,103,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216,103,197, 6, + 0, 0, 0, 0,248,102,197, 6, 0, 0, 0, 0, 72, 97,197, 6, 0, 0, 0, 0,152, 98,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,103,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72,104,197, 6, + 0, 0, 0, 0,104,103,197, 6, 0, 0, 0, 0,184, 97,197, 6, 0, 0, 0, 0, 8, 99,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72,104,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184,104,197, 6, + 0, 0, 0, 0,216,103,197, 6, 0, 0, 0, 0,152, 98,197, 6, 0, 0, 0, 0, 8, 99,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184,104,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40,105,197, 6, + 0, 0, 0, 0, 72,104,197, 6, 0, 0, 0, 0, 8, 99,197, 6, 0, 0, 0, 0,120, 99,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,105,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152,105,197, 6, + 0, 0, 0, 0,184,104,197, 6, 0, 0, 0, 0, 40, 98,197, 6, 0, 0, 0, 0,232, 99,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,152,105,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8,106,197, 6, + 0, 0, 0, 0, 40,105,197, 6, 0, 0, 0, 0,216, 96,197, 6, 0, 0, 0, 0, 88,100,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 8,106,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120,106,197, 6, + 0, 0, 0, 0,152,105,197, 6, 0, 0, 0, 0,152, 98,197, 6, 0, 0, 0, 0, 88,100,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,120,106,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232,106,197, 6, + 0, 0, 0, 0, 8,106,197, 6, 0, 0, 0, 0,120, 99,197, 6, 0, 0, 0, 0,200,100,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232,106,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88,107,197, 6, + 0, 0, 0, 0,120,106,197, 6, 0, 0, 0, 0,232, 99,197, 6, 0, 0, 0, 0,200,100,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88,107,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200,107,197, 6, + 0, 0, 0, 0,232,106,197, 6, 0, 0, 0, 0, 88,100,197, 6, 0, 0, 0, 0, 56,101,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,107,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56,108,197, 6, + 0, 0, 0, 0, 88,107,197, 6, 0, 0, 0, 0,200,100,197, 6, 0, 0, 0, 0, 56,101,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,108,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168,108,197, 6, + 0, 0, 0, 0,200,107,197, 6, 0, 0, 0, 0,232, 99,197, 6, 0, 0, 0, 0,168,101,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168,108,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24,109,197, 6, + 0, 0, 0, 0, 56,108,197, 6, 0, 0, 0, 0,120, 99,197, 6, 0, 0, 0, 0,168,101,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24,109,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136,109,197, 6, + 0, 0, 0, 0,168,108,197, 6, 0, 0, 0, 0, 8, 99,197, 6, 0, 0, 0, 0, 24,102,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136,109,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248,109,197, 6, + 0, 0, 0, 0, 24,109,197, 6, 0, 0, 0, 0, 40, 98,197, 6, 0, 0, 0, 0, 24,102,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248,109,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104,110,197, 6, + 0, 0, 0, 0,136,109,197, 6, 0, 0, 0, 0,168,101,197, 6, 0, 0, 0, 0, 24,102,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104,110,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216,110,197, 6, + 0, 0, 0, 0,248,109,197, 6, 0, 0, 0, 0,152, 98,197, 6, 0, 0, 0, 0,136,102,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,110,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72,111,197, 6, + 0, 0, 0, 0,104,110,197, 6, 0, 0, 0, 0,120, 99,197, 6, 0, 0, 0, 0,136,102,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72,111,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184,111,197, 6, + 0, 0, 0, 0,216,110,197, 6, 0, 0, 0, 0, 56,101,197, 6, 0, 0, 0, 0,136,102,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184,111,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40,112,197, 6, + 0, 0, 0, 0, 72,111,197, 6, 0, 0, 0, 0, 88,100,197, 6, 0, 0, 0, 0,200,100,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,112,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,184,111,197, 6, 0, 0, 0, 0,216, 96,197, 6, 0, 0, 0, 0,232, 99,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,152,112,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,104,116,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 98,197, 6, 0, 0, 0, 0, 72, 97,197, 6, 0, 0, 0, 0,184, 97,197, 6, + 0, 0, 0, 0, 8, 99,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,169, 3, 0, 0, + 5, 4, 0, 0, 7, 7,127, 7, 93, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,174,197, 6, + 0, 0, 0, 0,104,174,197, 6, 0, 0, 0, 0,136,113,197, 6, 0, 0, 0, 0,248,114,197, 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, 68, 65, 84, 65, + 40, 1, 0, 0,136,113,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,248,114,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,148, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, 0, 0, 0, 0, + 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, 0,192,239, 68, + 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, 26, 0,127, 7, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,236, 3, 0, 0, + 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, + 40, 1, 0, 0,248,114,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,113,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0,192,239, 68, 0, 0, 0, 0, 0, 0, 28, 66, 0, 0, 0, 0, 0,192,237, 68, 0, 0, 0, 0, + 0, 0,134, 66,110, 7, 0, 0,127, 7, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,109, 7, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 2, 2, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,127, 7, 67, 0,110, 7, + 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,169, 3, 0, 0, +235, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, +160, 0, 0, 0,104,116,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,248,140,197, 6, 0, 0, 0, 0,152,112,197, 6, + 0, 0, 0, 0,232, 99,197, 6, 0, 0, 0, 0,168,101,197, 6, 0, 0, 0, 0, 24,102,197, 6, 0, 0, 0, 0, 40, 98,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 5, 0, 0,126, 7, 0, 0, 0, 0, 0, 0,235, 2, 0, 0, 4, 4,142, 1, +236, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,139,197, 6, 0, 0, 0, 0,184,139,197, 6, + 0, 0, 0, 0, 88,117,197, 6, 0, 0, 0, 0,200,118,197, 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, 68, 65, 84, 65, 40, 1, 0, 0, 88,117,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,200,118,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,148, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,199, 67, 0, 0, 0, 0, 0, 0,208, 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, +141, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,198, 67, 0, 0,200, 65, 0,128,198, 67, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,142, 1, 26, 0,142, 1, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 5, 0, 0,126, 7, 0, 0,210, 2, 0, 0,235, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,200,118,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,117,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0,128,198, 67, 0, 0, 61,196, 0, 0, 0, 0, 0, 0, 0, 0,254,127,190, 67,254,127, 52,196, 0, 0, 0, 0,125, 1, 0, 0, +142, 1, 0, 0, 0, 0, 0, 0,209, 2, 0, 0, 0, 0, 0, 0,126, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +124, 1, 0, 0, 0, 0, 0, 0,209, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 1, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,142, 1,210, 2,125, 1,210, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 5, 0, 0,126, 7, 0, 0, 0, 0, 0, 0,209, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 1,210, 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, 56,120,197, 6, 0, 0, 0, 0, 24,138,197, 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, 68, 65, 84, 65, 88, 1, 0, 0, 56,120,197, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,216,121,197, 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, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101,120,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, 67,111,110,116,101,120,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,220,255,124, 1, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,216,121,197, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,120,123,197, 6, + 0, 0, 0, 0, 56,120,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100, +101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255, +124, 1, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,232,119,216, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,232,119,216, 3, 0, 0, 0, 0, 12, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 79, 66, 0, 0,112, 5, 0, 0,200,213,217, 3, 0, 0, 0, 0,129, 0, 0, 0, 1, 0, 0, 0,184,219,217, 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, 79, 66, 67, 97, -109,101,114, 97, 0, 97,109,101,114, 97, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,120,123,197, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 24,125,197, 6, 0, 0, 0, 0,216,121,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,255,124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 24,125,197, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,184,126,197, 6, + 0, 0, 0, 0,120,123,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101, +110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140,254, +124, 1,203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 24, 98,200, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 10, 0, 0, 0, - 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,184,126,197, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 88,128,197, 6, 0, 0, 0, 0, 24,125,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105, +110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105, +110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,110,116,105, 45, 65,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58,254,124, 1, 58, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0, 88,128,197, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,248,129,197, 6, + 0, 0, 0, 0,184,126,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,109,111,116,105,111,110, 95, 98,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97,109,112, +108,101,100, 32, 77,111,116,105,111,110, 32, 66,108,117,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,254, +124, 1, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,248,129,197, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,152,131,197, 6, 0, 0, 0, 0, 88,128,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,254,124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,152,131,197, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 56,133,197, 6, + 0, 0, 0, 0,248,129,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,101,114,102, +111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,242,253, +124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 56,133,197, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,216,134,197, 6, 0, 0, 0, 0,152,131,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101, +115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,112,111,115,116, 95,112,114,111, 99,101, +115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,111,115,116, 32, 80,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,218,253,124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 88, 1, 0, 0,216,134,197, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,120,136,197, 6, + 0, 0, 0, 0, 56,133,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,116, 97,109, +112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194,253, +124, 1, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0,120,136,197, 6, + 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 24,138,197, 6, 0, 0, 0, 0,216,134,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, 82, 69, 78, 68, 69, 82, 95, 80, 84, 95,111,117,116,112,117,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, 79,117,116,112,117,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, 40,253,124, 1,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,110,101,239, 64, -150, 62,208,192, 78,255,170, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 42,254,141, 63,192, 57, 49, 60, 34,159, 80, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,222,149, 47, 63, - 53, 70, 58, 63,222, 56, 49,188, 0, 0, 0, 0, 86,126,162,190,227,251,159, 62, 55, 53,101, 63, 0, 0, 0, 0, 7,165, 39, 63, -149, 84, 28,191, 51,247,227, 62, 0, 0, 0, 0,110,101,239, 64,150, 62,208,192, 78,255,170, 64, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 1, 0,128, 63, - 1, 0,128, 51, 1, 0, 0,179, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0,128, 63, 1, 0,128, 51, 0, 0, 0, 0, 2, 0, 0,179, - 2, 0, 0,167, 1, 0,128, 63, 0, 0, 0, 0, 1, 0, 0, 53, 1, 0, 0, 41, 1, 0,128,168, 0, 0,128, 63,221,149, 47, 63, - 86,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63,225,251,159, 62,149, 84, 28,191, 0, 0, 0, 0,192, 56, 49,188, - 55, 53,101, 63, 52,247,227, 62, 0, 0, 0, 0, 90, 38,173,190, 0,222,192,190,152, 9, 52,193, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 88, 1, 0, 0, 24,138,197, 6, 0, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,120,136,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 69, 78, 68, + 69, 82, 95, 80, 84, 95, 98, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 97,107,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,253, +124, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,184,139,197, 6, + 0, 0, 0, 0,179, 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, 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, 2, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 21, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,248,140,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,136,154,197, 6, + 0, 0, 0, 0,104,116,197, 6, 0, 0, 0, 0, 56,101,197, 6, 0, 0, 0, 0,136,102,197, 6, 0, 0, 0, 0,120, 99,197, 6, + 0, 0, 0, 0,200,100,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,249, 2, 0, 0,239, 5, 0, 0,105, 1, 0, 0, +167, 3, 0, 0, 1, 1,247, 2, 63, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,152,197, 6, + 0, 0, 0, 0,216,152,197, 6, 0, 0, 0, 0,232,141,197, 6, 0, 0, 0, 0,168,147,197, 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, 68, 65, 84, 65, + 40, 1, 0, 0,232,141,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 88,143,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,113, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,192, 61, 68, 0, 0, 0, 0, + 0, 0,208, 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,246, 2, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128, 61, 68, 0, 0,200, 65, 0,128, 61, 68, + 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,247, 2, 26, 0,247, 2, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,249, 2, 0, 0,239, 5, 0, 0,105, 1, 0, 0, +130, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,247, 2, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, + 40, 1, 0, 0, 88,143,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,200,144,197, 6, 0, 0, 0, 0,232,141,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0, 64, 70,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67,255,127, 70,196, + 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0, 43, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,160, 0, 44, 3,143, 0, + 26, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,249, 2, 0, 0,249, 2, 0, 0,131, 1, 0, 0, +167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 37, 2, 0, 0, 5, 0, 3, 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, 68, 65, 84, 65, + 40, 1, 0, 0,200,144,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 56,146,197, 6, 0, 0, 0, 0, 88,143,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 67, 0, 0,206,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, 0, 0,206,194, + 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0, +102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,249, 2, 0, 0,239, 5, 0, 0,131, 1, 0, 0, +131, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 6, 0, 34, 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, 68, 65, 84, 65, + 40, 1, 0, 0, 56,146,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,168,147,197, 6, 0, 0, 0, 0,200,144,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0,128,142,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0, 0, 26,196, + 0, 0, 0, 0,163, 0, 0, 0,180, 0, 0, 0, 18, 0, 0, 0,121, 2, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 18, 0, 0, 0,121, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,180, 0,122, 2,163, 0, +104, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,239, 5, 0, 0,239, 5, 0, 0,131, 1, 0, 0, +167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, + 40, 1, 0, 0,168,147,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,146,197, 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,249, 2, 0, 0,239, 5, 0, 0,131, 1, 0, 0, +167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,247, 2, 37, 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, 24,149,197, 6, 0, 0, 0, 0, 68, 65, 84, 65, +112, 3, 0, 0, 24,149,197, 6, 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 74,141,193, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, + 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,225,215,163,188, 0, 0, 0, 0, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, + 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,214,211,111,193, 0, 0,128, 63, 69,239,209, 62, 70,119,105, 63,176, 84, 89,188, + 0, 0, 0, 0, 53,177,205,190,142, 74, 70, 62,166, 33,101, 63, 0, 0, 0, 0,185,158, 81, 63, 35, 44,185,190, 43, 61,228, 62, + 0, 0, 0, 0,164, 96, 68, 65,111,121,173,192,248,209,213, 64, 0, 0,128, 63,178,157,229, 62, 30,132, 27,191,222,160, 81,191, +184,158, 81,191,117, 90,127, 63,166,235,149, 62, 9, 46,185, 62, 35, 44,185, 62,145,180,109,188,212, 60,173, 63,129, 63,228,190, + 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0, 96,132,111, 65,214,211,111, 65,217,236,191, 62, 54,117, 85, 63,224,246, 70,188, + 0,160, 32,182,252, 5,136,190, 43, 33, 3, 62,235,135, 23, 63, 0, 0, 96, 53,215,104, 25,196,133,132,135, 67, 37, 9,167,195, +136,252, 71,194, 3, 54, 25, 68,158, 87,135,195,205,209,166, 67,151,254, 71, 66, 68,239,209, 62, 51,177,205,190,184,158, 81, 63, + 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, 42, 61,228, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,214,211,111,193, 0, 0,128, 63,178,157,229, 62, 30,132, 27,191,222,160, 81,191, +184,158, 81,191,117, 90,127, 63,166,235,149, 62, 9, 46,185, 62, 35, 44,185, 62,145,180,109,188,212, 60,173, 63,129, 63,228,190, + 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0, 96,132,111, 65,214,211,111, 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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 86, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 46, 86, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 86, 45, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 92, 62, 55, 63, 56,186,224,190,237,203,148,190, + 3,236,234,190,214,211,111, 65,214,211,111, 65, 0, 0, 0, 0, 0, 0, 0, 0,107,227, 29, 59, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 30, 33, 12, 66, 86,152,137, 66,116, 27,126, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 96, 1, 0, 0,216,152,197, 6, 0, 0, 0, 0,174, 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, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 56,180,150,201, 0, 0,128, 63,187,225, 16, 63, 0, 0,128, 63,205,204,204, 62, -237, 54, 32, 63, 0, 0, 0, 0,143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 2, 0, 1, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32, 65,205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,200, 67,198, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 40,215, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, 8, 8,128, 0, + 0, 0, 12, 66, 0, 0,128, 63, 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 10, 0, 7, 1, 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, 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, 68, 65, 84, 65, +160, 0, 0, 0,136,154,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,232,160,197, 6, 0, 0, 0, 0,248,140,197, 6, + 0, 0, 0, 0,216, 96,197, 6, 0, 0, 0, 0, 88,100,197, 6, 0, 0, 0, 0,200,100,197, 6, 0, 0, 0, 0,232, 99,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,239, 5, 0, 0, 0, 0, 0, 0,103, 1, 0, 0, 18, 18,240, 5, +104, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,159,197, 6, 0, 0, 0, 0, 24,159,197, 6, + 0, 0, 0, 0,120,155,197, 6, 0, 0, 0, 0,232,156,197, 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, 68, 65, 84, 65, 40, 1, 0, 0,120,155,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,232,156,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,128,160, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,190, 68, 0, 0, 0, 0, 0, 0,208, 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, 68, 65, 84, 65,152, 0, 0, 0,248, 40,215, 3, 0, 0, 0, 0,132, 0, 0, 0, - 1, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, +239, 5, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,224,189, 68, 0, 0,200, 65, 0,224,189, 68, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,240, 5, 26, 0,240, 5, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,239, 5, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 5, 26, 0, 0, 0, 1, 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,205,204,204, 61, -205,204, 76, 62, 10,215,163, 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, 2, 0, 0, 0, 79, 66, 0, 0, -112, 5, 0, 0,184,219,217, 3, 0, 0, 0, 0,129, 0, 0, 0, 1, 0, 0, 0,168,225,217, 3, 0, 0, 0, 0,200,213,217, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 67,117, 98,101, 0,112,104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 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, 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, 68, 65, 84, 65, 40, 1, 0, 0,232,156,197, 6, + 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,155,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0,224,189, 68, 0, 0, 0, 0, 0, 0, 51, 67, 0, 0, 0, 0, 0,224,187, 68, 0, 0, 0, 0, 0, 0,167, 67,223, 5, 0, 0, +240, 5, 0, 0, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +222, 5, 0, 0, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 2, 2, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,240, 5, 78, 1,223, 5, 78, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,239, 5, 0, 0, 26, 0, 0, 0,103, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 5, 78, 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, 68, 65, 84, 65, 40, 0, 0, 0, 88,158,197, 6, + 0, 0, 0, 0,193, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0,200,158,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0,200,158,197, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,136, 1, 0, 0, 24,159,197, 6, 0, 0, 0, 0, +194, 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, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,158,197, 6, 0, 0, 0, 0, + 88,158,197, 6, 0, 0, 0, 0, 62, 62, 62, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,112,121,116,104,111,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 4, 0, 0, 8, 4, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,232,160,197, 6, 0, 0, 0, 0, +214, 0, 0, 0, 1, 0, 0, 0,168,167,197, 6, 0, 0, 0, 0,136,154,197, 6, 0, 0, 0, 0,168,101,197, 6, 0, 0, 0, 0, +120, 99,197, 6, 0, 0, 0, 0, 8, 99,197, 6, 0, 0, 0, 0, 24,102,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +241, 5, 0, 0,126, 7, 0, 0,237, 2, 0, 0,167, 3, 0, 0, 3, 3,142, 1,187, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,184,164,197, 6, 0, 0, 0, 0,184,164,197, 6, 0, 0, 0, 0,216,161,197, 6, 0, 0, 0, 0, + 72,163,197, 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, 68, 65, 84, 65, 40, 1, 0, 0,216,161,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, + 72,163,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,244, 67, 0, 0, 0, 0, 0, 0,208, 65, + 0, 0, 0, 0, 0, 0,199, 67, 0, 0, 0, 0, 0, 0,208, 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,141, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, + 0,128,198, 67, 0, 0,200, 65, 0,128,198, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, + 4, 0, 12, 0, 10, 0,142, 1, 26, 0,142, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +241, 5, 0, 0,126, 7, 0, 0,237, 2, 0, 0, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +142, 1, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72,163,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,216,161,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,141, 67, 0, 0,244,194, 0, 0, 0, 0, + 0, 0, 0, 0, 0,128,190, 67, 0, 0, 15,195, 0, 0, 0, 0,125, 1, 0, 0,142, 1, 0, 0, 18, 0, 0, 0,160, 0, 0, 0, + 0, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 18, 0, 0, 0,160, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 18, 6, 0, 0, 2, 0, 3, 3, + 0, 0, 12, 4, 6, 0,142, 1,161, 0,125, 1,143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +241, 5, 0, 0,126, 7, 0, 0, 7, 3, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +142, 1,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 1, 0, 0,184,164,197, 6, 0, 0, 0, 0,183, 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, + 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, 24,166,197, 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, 1, 0, 0, 0, 68, 65, 84, 65, 16, 0, 0, 0, + 24,166,197, 6, 0, 0, 0, 0,237, 0, 0, 0, 1, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0,120,166,197, 6, 0, 0, 0, 0, + 68, 65, 84, 65,224, 0, 0, 0,120,166,197, 6, 0, 0, 0, 0,236, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +104, 38,198, 6, 0, 0, 0, 0, 19, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 20, 0, 0, 0, 1, 0, 1, 0, +104, 38,198, 6, 0, 0, 0, 0, 21, 0, 1, 0, 1, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, +248, 64,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,104, 74,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 8,129,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 72, 88,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 88,110,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,168, 81,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 56, 60,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,200, 67,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 40, 59,198, 6, 0, 0, 0, 0, 21, 0, 0, 0, 1, 0, 1, 0,104, 38,198, 6, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, +168,167,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,160,197, 6, 0, 0, 0, 0, + 88,100,197, 6, 0, 0, 0, 0,152, 98,197, 6, 0, 0, 0, 0,136,102,197, 6, 0, 0, 0, 0, 56,101,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,247, 2, 0, 0,105, 1, 0, 0,167, 3, 0, 0, 9, 9,248, 2, 63, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,171,197, 6, 0, 0, 0, 0,120,171,197, 6, 0, 0, 0, 0, +152,168,197, 6, 0, 0, 0, 0, 8,170,197, 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, 68, 65, 84, 65, 40, 1, 0, 0,152,168,197, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0, 8,170,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230, 67, + 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 62, 68, 0, 0, 0, 0, 0, 0,208, 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,247, 2, 0, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 0,192, 61, 68, 0, 0,200, 65, 0,192, 61, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,248, 2, 26, 0,248, 2, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,247, 2, 0, 0,105, 1, 0, 0,130, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,248, 2, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8,170,197, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,168,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,189, 68, + 0, 0, 0, 0, 0,192, 22, 68,248,150, 23, 68, 8, 41,100, 68, 46,224, 62, 67,233, 15,206, 67, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,247, 2, 0, 0, + 0, 0, 0, 0, 36, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,215, 35, 60, 0, 0,122, 68, + 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 4, 10, 0,248, 2, 37, 2,248, 2, 37, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,247, 2, 0, 0,131, 1, 0, 0,167, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,248, 2, 37, 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, 68, 65, 84, 65,160, 2, 0, 0,120,171,197, 6, 0, 0, 0, 0, +186, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 12, 0, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61,231, 1, 0, 0,243, 1, 0, 0,122, 1, 0, 0,124, 1, 0, 0, +231, 1, 0, 0,243, 1, 0, 0, 4, 0, 0, 0,124, 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, 83, 78, 0, 0, 8, 1, 0, 0,248,174,197, 6, 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0, + 24,246,197, 6, 0, 0, 0, 0,136, 95,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 83, 82, 85, 86, 32, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,176,197, 6, 0, 0, 0, 0, + 88,179,197, 6, 0, 0, 0, 0,200,179,197, 6, 0, 0, 0, 0, 40,184,197, 6, 0, 0, 0, 0,152,184,197, 6, 0, 0, 0, 0, +184,228,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 32, 0, 0, 0, 72,176,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, +184,176,197, 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, + 68, 65, 84, 65, 32, 0, 0, 0,184,176,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 40,177,197, 6, 0, 0, 0, 0, + 72,176,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, + 40,177,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,152,177,197, 6, 0, 0, 0, 0,184,176,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 5, 4, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,152,177,197, 6, 0, 0, 0, 0, +211, 0, 0, 0, 1, 0, 0, 0, 8,178,197, 6, 0, 0, 0, 0, 40,177,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +126, 7, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8,178,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, +120,178,197, 6, 0, 0, 0, 0,152,177,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,234, 3, 1, 0, 0, 0, + 68, 65, 84, 65, 32, 0, 0, 0,120,178,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,232,178,197, 6, 0, 0, 0, 0, + 8,178,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, +232,178,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 88,179,197, 6, 0, 0, 0, 0,120,178,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,200, 3,234, 3, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 88,179,197, 6, 0, 0, 0, 0, +211, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,178,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +200, 3, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200,179,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, + 56,180,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,176,197, 6, 0, 0, 0, 0, 40,177,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56,180,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, +168,180,197, 6, 0, 0, 0, 0,200,179,197, 6, 0, 0, 0, 0,184,176,197, 6, 0, 0, 0, 0, 8,178,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,168,180,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, + 24,181,197, 6, 0, 0, 0, 0, 56,180,197, 6, 0, 0, 0, 0, 40,177,197, 6, 0, 0, 0, 0,120,178,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 24,181,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, +136,181,197, 6, 0, 0, 0, 0,168,180,197, 6, 0, 0, 0, 0, 8,178,197, 6, 0, 0, 0, 0,120,178,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,136,181,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, +248,181,197, 6, 0, 0, 0, 0, 24,181,197, 6, 0, 0, 0, 0, 8,178,197, 6, 0, 0, 0, 0,232,178,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,248,181,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, +104,182,197, 6, 0, 0, 0, 0,136,181,197, 6, 0, 0, 0, 0, 72,176,197, 6, 0, 0, 0, 0, 88,179,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,104,182,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, +216,182,197, 6, 0, 0, 0, 0,248,181,197, 6, 0, 0, 0, 0, 72,176,197, 6, 0, 0, 0, 0, 8,178,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,216,182,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, + 72,183,197, 6, 0, 0, 0, 0,104,182,197, 6, 0, 0, 0, 0,232,178,197, 6, 0, 0, 0, 0, 88,179,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 72,183,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, +184,183,197, 6, 0, 0, 0, 0,216,182,197, 6, 0, 0, 0, 0,120,178,197, 6, 0, 0, 0, 0,232,178,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,184,183,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, + 40,184,197, 6, 0, 0, 0, 0, 72,183,197, 6, 0, 0, 0, 0,152,177,197, 6, 0, 0, 0, 0, 88,179,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 40,184,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,184,183,197, 6, 0, 0, 0, 0,152,177,197, 6, 0, 0, 0, 0,120,178,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,152,184,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, +104,188,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,178,197, 6, 0, 0, 0, 0,184,176,197, 6, 0, 0, 0, 0, + 40,177,197, 6, 0, 0, 0, 0,120,178,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, +235, 3, 0, 0, 5, 4, 0, 0, 7, 7,127, 7, 27, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +136,245,197, 6, 0, 0, 0, 0,136,245,197, 6, 0, 0, 0, 0,136,185,197, 6, 0, 0, 0, 0,248,186,197, 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, + 68, 65, 84, 65, 40, 1, 0, 0,136,185,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,248,186,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,148, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,239, 68, + 0, 0, 0, 0, 0, 0,208, 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,126, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,239, 68, 0, 0,200, 65, + 0,192,239, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,127, 7, + 26, 0,127, 7, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0, +235, 3, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 7, 26, 0, 0, 0, 1, 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, + 68, 65, 84, 65, 40, 1, 0, 0,248,186,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +136,185,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,109, 69, 0, 0,128,192, 0, 0, 0, 0, 0, 0, 0, 0,255,255,109, 69, + 0, 0, 0,192, 0, 0, 0, 0,112, 7, 0, 0,129, 7, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 18, 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,128, 63, 0, 0,128, 63, 2, 0, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,129, 7, + 2, 0,112, 7, 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, + 5, 4, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, + 0, 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, + 68, 65, 84, 65,160, 0, 0, 0,104,188,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,184,228,197, 6, 0, 0, 0, 0, +152,184,197, 6, 0, 0, 0, 0, 72,176,197, 6, 0, 0, 0, 0, 8,178,197, 6, 0, 0, 0, 0,232,178,197, 6, 0, 0, 0, 0, + 88,179,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,199, 3, 0, 0, 0, 0, 0, 0,233, 3, 0, 0, + 6, 6,200, 3,234, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,195,197, 6, 0, 0, 0, 0, + 72,195,197, 6, 0, 0, 0, 0, 88,189,197, 6, 0, 0, 0, 0,216,193,197, 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, 68, 65, 84, 65, 40, 1, 0, 0, + 88,189,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,200,190,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,215, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,114, 68, 0, 0, 0, 0, 0, 0,208, 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,199, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192,113, 68, 0, 0,200, 65, 0,192,113, 68, 0, 0,200, 65, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,200, 3, 26, 0,200, 3, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,199, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 3, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, +200,190,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,216,193,197, 6, 0, 0, 0, 0, 88,189,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 91, 67, 0,192,115,196, 0, 0, 0, 0, 0, 0, 0, 0,254,255, 74, 67,254,255,115,196, 0, 0, 0, 0, +203, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0,207, 3, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0,207, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,220, 0,208, 3,203, 0,208, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,219, 0, 0, 0, 26, 0, 0, 0,233, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,208, 3, 0, 0, 4, 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, 56,192,197, 6, 0, 0, 0, 0, 56,192,197, 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, 68, 65, 84, 65, 88, 1, 0, 0, + 56,192,197, 6, 0, 0, 0, 0,213, 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, 73, 77, 65, 71, 69, 95, 80, 84, 95,103,112,101,110, 99,105,108, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 77, 65, 71, 69, 95, 80, 84, 95,103,112,101,110, 99,105,108, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71,114,101, 97,115,101, 32, 80,101,110, 99,105,108, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,255,202, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,216,193,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,200,190,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 67, + 51, 51, 43,191,154,153,213, 63, 51, 51,131,191,154,153, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,236, 2, 0, 0, 0, 0, 0, 0,208, 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, +220, 0, 0, 0,199, 3, 0, 0, 26, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +236, 2,208, 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, 68, 65, 84, 65, 40, 33, 0, 0, 72,195,197, 6, 0, 0, 0, 0,184, 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, + 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,100, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 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,240, 65, 0, 0, 0, 0,154,153,153, 62, 0, 0, 0, 0,100, 0, 0, 0, +154,153,153, 62,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,184,228,197, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,104,188,197, 6, 0, 0, 0, 0, 88,179,197, 6, 0, 0, 0, 0,232,178,197, 6, 0, 0, 0, 0, +120,178,197, 6, 0, 0, 0, 0,152,177,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,201, 3, 0, 0,126, 7, 0, 0, + 0, 0, 0, 0,233, 3, 0, 0, 1, 1,182, 3,234, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +216,243,197, 6, 0, 0, 0, 0,216,243,197, 6, 0, 0, 0, 0,168,229,197, 6, 0, 0, 0, 0,168,238,197, 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, + 68, 65, 84, 65, 40, 1, 0, 0,168,229,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 24,231,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,113, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,128,109, 68, + 0, 0, 0, 0, 0, 0,208, 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,181, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 64,109, 68, 0, 0,200, 65, + 0, 64,109, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,182, 3, + 26, 0,182, 3, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,201, 3, 0, 0,126, 7, 0, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,182, 3, 26, 0, 0, 0, 1, 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, + 68, 65, 84, 65, 40, 1, 0, 0, 24,231,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 40,234,197, 6, 0, 0, 0, 0, +168,229,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 67, 0, 0, 86,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, + 0, 0, 86,196, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 87, 3, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 87, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0, + 88, 3,143, 0, 88, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,201, 3, 0, 0,104, 4, 0, 0, +146, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 88, 3, 0, 0, 5, 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,136,232,197, 6, 0, 0, 0, 0,136,232,197, 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, + 68, 65, 84, 65, 88, 1, 0, 0,136,232,197, 6, 0, 0, 0, 0,213, 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, 86, 73, 69, 87, 51, 68, 95, 80, + 84, 95,116,111,111,108,115, 95,111, 98,106,101, 99,116,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, + 84, 95,116,111,111,108,115, 95,111, 98,106,101, 99,116,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 98,106,101, 99,116, 32, 84, +111,111,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,233,253,143, 0,255, 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, 68, 65, 84, 65, 40, 1, 0, 0, 40,234,197, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0, 56,237,197, 6, 0, 0, 0, 0, 24,231,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 67, + 0, 0,242,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, 91, 90,242,194, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, + 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, + 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, + 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,201, 3, 0, 0,104, 4, 0, 0, 26, 0, 0, 0,145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,160, 0,120, 0, 0, 0, 6, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +152,235,197, 6, 0, 0, 0, 0,152,235,197, 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, 68, 65, 84, 65, 88, 1, 0, 0,152,235,197, 6, 0, 0, 0, 0, +213, 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, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 79,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,255,144, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 1, 0, 0, 56,237,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,168,238,197, 6, 0, 0, 0, 0, + 40,234,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, 0,128,126,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 67, +255,191,126,196, 0, 0, 0, 0,163, 0, 0, 0,180, 0, 0, 0, 18, 0, 0, 0, 12, 4, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 18, 0, 0, 0, 12, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,180, 0, + 13, 4,163, 0,251, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 7, 0, 0,126, 7, 0, 0, + 26, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, + 68, 65, 84, 65, 40, 1, 0, 0,168,238,197, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56,237,197, 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,105, 4, 0, 0,126, 7, 0, 0, + 26, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 3,208, 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, 24,240,197, 6, 0, 0, 0, 0, + 68, 65, 84, 65,112, 3, 0, 0, 24,240,197, 6, 0, 0, 0, 0,173, 0, 0, 0, 1, 0, 0, 0, 72,246,172, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 28, 13,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0, 74,215, 76,190, 0, 0, 0, 0, 68,239,209, 62, 51,177,205,190, +184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, + 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 95,192, 0, 0,128, 63, 69,239,209, 62, 70,119,105, 63, +160, 84, 89,188, 0, 0, 0, 0, 52,177,205,190,142, 74, 70, 62,166, 33,101, 63, 0, 0, 0, 0,185,158, 81, 63, 35, 44,185,190, + 43, 61,228, 62, 0, 0, 0, 0,188,173, 54, 64,136, 95,161,191,147,231,198, 63, 0, 0,128, 63,185,214, 13, 63,208,249,224,190, + 48,180, 81,191,184,158, 81,191,189,188,157, 63,140,225, 88, 62, 26, 63,185, 62, 35, 44,185, 62,241,213,146,188,206,156,122, 63, +138, 84,228,190, 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0,100, 98, 82, 64, 0, 25, 95, 64,121, 92,155, 62,151,198, 44, 63, +192,214, 32,188, 0, 0, 40,180,195, 15,188,190,132, 75, 53, 62,216,125, 81, 63, 0, 0,192,179,115, 77,100,193, 17,173,201, 64, +181,148,248,192,203,247,159,192,233, 74, 87, 65,247, 46,190,192, 88,106,234, 64, 45, 8,160, 64, 68,239,209, 62, 51,177,205,190, +184,158, 81, 63, 0, 0, 0, 0, 70,119,105, 63,143, 74, 70, 62, 35, 44,185,190, 0, 0, 0, 0,162, 84, 89,188,166, 33,101, 63, + 42, 61,228, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 95,192, 0, 0,128, 63,185,214, 13, 63,208,249,224,190, + 48,180, 81,191,184,158, 81,191,189,188,157, 63,140,225, 88, 62, 26, 63,185, 62, 35, 44,185, 62,241,213,146,188,206,156,122, 63, +138, 84,228,190, 42, 61,228,190, 0, 0, 0, 0, 0, 0, 0, 0,100, 98, 82, 64, 0, 25, 95, 64, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,201,250, 62, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,201,250, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +248,201,250, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 92, 62, 55, 63, 56,186,224,190, +237,203,148,190, 3,236,234,190, 0, 25, 95, 64, 0, 25, 95, 64, 0, 0, 0, 0, 0, 0, 0, 0,114,145,245, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 30, 33, 12, 66, 85,152,137, 66,116, 27,126, 66, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 1, 0, 0,216,243,197, 6, 0, 0, 0, 0,174, 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, + 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65,205,204, 76, 62, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0, +200, 67,198, 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, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 3, 0, + 8, 8,128, 0, 0, 0, 12, 66, 0, 0,128, 63,205,204,204, 61, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 10, 0, 7, 1, 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, + 83, 78, 0, 0, 8, 1, 0, 0, 24,246,197, 6, 0, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +248,174,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 86,105,100,101,111, 32, + 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,247,197, 6, 0, 0, 0, 0, 56,252,197, 6, 0, 0, 0, 0, +168,252,197, 6, 0, 0, 0, 0, 24, 4,198, 6, 0, 0, 0, 0,136, 4,198, 6, 0, 0, 0, 0,232, 29,198, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 38,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, + 68, 65, 84, 65, 32, 0, 0, 0,104,247,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,216,247,197, 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, 68, 65, 84, 65, 32, 0, 0, 0, +216,247,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 72,248,197, 6, 0, 0, 0, 0,104,247,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,222, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 72,248,197, 6, 0, 0, 0, 0, +211, 0, 0, 0, 1, 0, 0, 0,184,248,197, 6, 0, 0, 0, 0,216,247,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +240, 4,222, 2, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,184,248,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, + 40,249,197, 6, 0, 0, 0, 0, 72,248,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 32, 0, 0, 0, 40,249,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,152,249,197, 6, 0, 0, 0, 0, +184,248,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, +152,249,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 8,250,197, 6, 0, 0, 0, 0, 40,249,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,240, 4,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 8,250,197, 6, 0, 0, 0, 0, +211, 0, 0, 0, 1, 0, 0, 0,120,250,197, 6, 0, 0, 0, 0,152,249,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +240, 4, 92, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,120,250,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, +232,250,197, 6, 0, 0, 0, 0, 8,250,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 32, 0, 0, 0,232,250,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 88,251,197, 6, 0, 0, 0, 0, +120,250,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 2,195, 2, 1, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, + 88,251,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0,200,251,197, 6, 0, 0, 0, 0,232,250,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0,200,251,197, 6, 0, 0, 0, 0, +211, 0, 0, 0, 1, 0, 0, 0, 56,252,197, 6, 0, 0, 0, 0, 88,251,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 2, 92, 1, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 56,252,197, 6, 0, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,200,251,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 68, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,168,252,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24,253,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,216,247,197, 6, 0, 0, 0, 0, 72,248,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0, 24,253,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,136,253,197, 6, 0, 0, 0, 0, +168,252,197, 6, 0, 0, 0, 0,216,247,197, 6, 0, 0, 0, 0, 40,249,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,136,253,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,248,253,197, 6, 0, 0, 0, 0, + 24,253,197, 6, 0, 0, 0, 0, 72,248,197, 6, 0, 0, 0, 0,152,249,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,248,253,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,104,254,197, 6, 0, 0, 0, 0, +136,253,197, 6, 0, 0, 0, 0, 40,249,197, 6, 0, 0, 0, 0,152,249,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,104,254,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,216,254,197, 6, 0, 0, 0, 0, +248,253,197, 6, 0, 0, 0, 0,152,249,197, 6, 0, 0, 0, 0, 8,250,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,216,254,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 72,255,197, 6, 0, 0, 0, 0, +104,254,197, 6, 0, 0, 0, 0,104,247,197, 6, 0, 0, 0, 0,120,250,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0, 72,255,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,184,255,197, 6, 0, 0, 0, 0, +216,254,197, 6, 0, 0, 0, 0, 40,249,197, 6, 0, 0, 0, 0,232,250,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,184,255,197, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 40, 0,198, 6, 0, 0, 0, 0, + 72,255,197, 6, 0, 0, 0, 0,120,250,197, 6, 0, 0, 0, 0, 88,251,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0, 40, 0,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,152, 0,198, 6, 0, 0, 0, 0, +184,255,197, 6, 0, 0, 0, 0, 88,251,197, 6, 0, 0, 0, 0,200,251,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,152, 0,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 8, 1,198, 6, 0, 0, 0, 0, + 40, 0,198, 6, 0, 0, 0, 0,232,250,197, 6, 0, 0, 0, 0,200,251,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0, 8, 1,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,120, 1,198, 6, 0, 0, 0, 0, +152, 0,198, 6, 0, 0, 0, 0, 8,250,197, 6, 0, 0, 0, 0, 56,252,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,120, 1,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,232, 1,198, 6, 0, 0, 0, 0, + 8, 1,198, 6, 0, 0, 0, 0,184,248,197, 6, 0, 0, 0, 0, 56,252,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,232, 1,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 88, 2,198, 6, 0, 0, 0, 0, +120, 1,198, 6, 0, 0, 0, 0,120,250,197, 6, 0, 0, 0, 0, 56,252,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0, 88, 2,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,200, 2,198, 6, 0, 0, 0, 0, +232, 1,198, 6, 0, 0, 0, 0,104,247,197, 6, 0, 0, 0, 0,184,248,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,200, 2,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 56, 3,198, 6, 0, 0, 0, 0, + 88, 2,198, 6, 0, 0, 0, 0,152,249,197, 6, 0, 0, 0, 0,232,250,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0, 56, 3,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,168, 3,198, 6, 0, 0, 0, 0, +200, 2,198, 6, 0, 0, 0, 0, 8,250,197, 6, 0, 0, 0, 0,200,251,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,168, 3,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 24, 4,198, 6, 0, 0, 0, 0, + 56, 3,198, 6, 0, 0, 0, 0, 40,249,197, 6, 0, 0, 0, 0, 88,251,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0, 24, 4,198, 6, 0, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +168, 3,198, 6, 0, 0, 0, 0, 8,250,197, 6, 0, 0, 0, 0, 88,251,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65,160, 0, 0, 0,136, 4,198, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 88, 8,198, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40,249,197, 6, 0, 0, 0, 0,216,247,197, 6, 0, 0, 0, 0, 72,248,197, 6, 0, 0, 0, 0, +152,249,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0,196, 2, 0, 0,222, 2, 0, 0, + 7, 7,241, 4, 27, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 37,198, 6, 0, 0, 0, 0, +216, 37,198, 6, 0, 0, 0, 0,120, 5,198, 6, 0, 0, 0, 0,232, 6,198, 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, 68, 65, 84, 65, 40, 1, 0, 0, +120, 5,198, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,232, 6,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,128,148, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 32,158, 68, 0, 0, 0, 0, 0, 0,208, 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,240, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0,158, 68, 0, 0,200, 65, 0, 0,158, 68, 0, 0,200, 65, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,241, 4, 26, 0,241, 4, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0,196, 2, 0, 0,221, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241, 4, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0, +232, 6,198, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 5,198, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0,240,109, 69, 0, 0,128,192, 0, 0, 0, 0, 0, 0, 0, 0,255,255,109, 69, 0, 0, 0,192, 0, 0, 0, 0, +112, 7, 0, 0,129, 7, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 0,111, 7, 0, 0, 18, 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,128, 63, 0, 0,128, 63, 2, 0, 0, 0, 1, 0, 3, 3, 2, 0, 0, 4, 10, 0,129, 7, 2, 0,112, 7, 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,222, 2, 0, 0,222, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65,160, 0, 0, 0, + 88, 8,198, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 72, 13,198, 6, 0, 0, 0, 0,136, 4,198, 6, 0, 0, 0, 0, +104,247,197, 6, 0, 0, 0, 0,120,250,197, 6, 0, 0, 0, 0, 56,252,197, 6, 0, 0, 0, 0,184,248,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 15, 15,241, 4, 68, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 12,198, 6, 0, 0, 0, 0, 40, 12,198, 6, 0, 0, 0, 0, + 72, 9,198, 6, 0, 0, 0, 0,184, 10,198, 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, 68, 65, 84, 65, 40, 1, 0, 0, 72, 9,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0,184, 10,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,140, 68, + 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 32,158, 68, 0, 0, 0, 0, 0, 0,208, 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,240, 4, 0, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 0, 0,158, 68, 0, 0,200, 65, 0, 0,158, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,241, 4, 26, 0,241, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,241, 4, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,184, 10,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 9,198, 6, 0, 0, 0, 0, 0, 0, 64,192, 0, 0,126, 67, + 0, 0, 0, 0, 0, 0, 72, 66,112,189, 17,192,246, 70,125, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, + 18, 0, 0, 0, 41, 0, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, + 72, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 4, 8, 0,241, 4, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, 26, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,241, 4, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,208, 0, 0, 0, 40, 12,198, 6, 0, 0, 0, 0, +190, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,107,205, 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,136, 48,218, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 10, 0, 0, 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, 31, 0, 0, 0, 1, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, + 72, 13,198, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 56, 21,198, 6, 0, 0, 0, 0, 88, 8,198, 6, 0, 0, 0, 0, +120,250,197, 6, 0, 0, 0, 0, 88,251,197, 6, 0, 0, 0, 0, 8,250,197, 6, 0, 0, 0, 0, 56,252,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, 69, 0, 0, 0, 91, 1, 0, 0, 8, 8,241, 4, 23, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 19,198, 6, 0, 0, 0, 0,248, 19,198, 6, 0, 0, 0, 0, + 56, 14,198, 6, 0, 0, 0, 0,136, 18,198, 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, 68, 65, 84, 65, 40, 1, 0, 0, 56, 14,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0,168, 15,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 26, 68, + 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 32,158, 68, 0, 0, 0, 0, 0, 0,208, 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,240, 4, 0, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 0, 0,158, 68, 0, 0,200, 65, 0, 0,158, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,241, 4, 26, 0,241, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 4, 0, 0, 69, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,241, 4, 26, 0, 0, 0, 1, 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,136, 12,217, 3, - 0, 0, 0, 0,168,182,117, 3, 0, 0, 0, 0, 1, 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,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,168, 15,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0, 24, 17,198, 6, 0, 0, 0, 0, 56, 14,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 67, + 0, 0,125,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 67, 1, 0,125,195, 0, 0, 0, 0,203, 0, 0, 0,220, 0, 0, 0, + 0, 0, 0, 0,252, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, + 0, 0, 0, 0,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, + 10, 3, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,220, 0,253, 0,203, 0,253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 21, 4, 0, 0,240, 4, 0, 0, 95, 0, 0, 0, 91, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,220, 0,253, 0, 0, 0, 4, 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, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 68, 0, 0, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, - 0, 0, 0, 0, 56,180,150,201, 0, 0,128, 63,169, 19,208, 60, 0, 0,128, 63,205,204,204, 62,229,208, 34, 62, 0, 0, 0, 0, -143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 5, 0, 1, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 24, 17,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0,136, 18,198, 6, 0, 0, 0, 0,168, 15,198, 6, 0, 0, 0, 0, 0, 0,112,196, 0, 0,112, 68, + 0, 0, 7,196, 0, 0, 7, 68, 0, 0,112,196, 0, 0,112, 68, 0, 0, 7,196, 0, 0, 7, 68, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 59, 70, 0,128, 59, 70,172,197, 39, 55, 0, 80,195, 71, + 0, 0, 0, 0, 0, 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, 20, 4, 0, 0, 91, 1, 0, 0, 91, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 7, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,136, 18,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 17,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 67, + 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 17, 0, 0, 0, + 18, 0, 0, 0,252, 0, 0, 0, 18, 0, 0, 0, 20, 4, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 20, 4, 0, 0, + 18, 0, 0, 0,252, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 63, 0,124,146, 72, 0, 0, 0, 66, 10,215, 35, 60, 0, 0,200, 66, +105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 0, 21, 4,253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 4, 0, 0, 95, 0, 0, 0, 91, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 21, 4,253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,240, 0, 0, 0,248, 19,198, 6, 0, 0, 0, 0, +180, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 64, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, + 56, 21,198, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,232, 29,198, 6, 0, 0, 0, 0, 72, 13,198, 6, 0, 0, 0, 0, + 88,251,197, 6, 0, 0, 0, 0, 40,249,197, 6, 0, 0, 0, 0,232,250,197, 6, 0, 0, 0, 0,200,251,197, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 2, 0, 0, 93, 1, 0, 0,194, 2, 0, 0, 2, 2, 48, 2,102, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232, 27,198, 6, 0, 0, 0, 0,232, 27,198, 6, 0, 0, 0, 0, + 40, 22,198, 6, 0, 0, 0, 0,120, 26,198, 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, 68, 65, 84, 65, 40, 1, 0, 0, 40, 22,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0,152, 23,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 89, 68, + 0, 0, 0, 0, 0, 0,208, 65,154,216, 65, 55, 0, 0, 12, 68, 0, 0, 0, 0, 0, 0,208, 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, 47, 2, 0, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 0,192, 11, 68, 0, 0,200, 65, 0,192, 11, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0, 48, 2, 26, 0, 48, 2, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 2, 0, 0, 93, 1, 0, 0,118, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 48, 2, 26, 0, 0, 0, 1, 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, 68, 65, 84, 65, 40, 1, 0, 0,152, 23,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0, 8, 25,198, 6, 0, 0, 0, 0, 40, 22,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 67, + 0, 0,112,193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 67, 0, 0,157,195, 0, 0, 0, 0,200, 0, 0, 0,217, 0, 0, 0, + 18, 0, 0, 0, 75, 1, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,199, 0, 0, 0, + 18, 0, 0, 0, 75, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 10, 6, 0, 0, 2, 0, 3, 3, 0, 0, 0, 4, 6, 0,217, 0, 76, 1,200, 0, 58, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 0, 0, 0,119, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,217, 0, 76, 1, 0, 0, 2, 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, 68, 65, 84, 65, 40, 1, 0, 0, 8, 25,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0,120, 26,198, 6, 0, 0, 0, 0,152, 23,198, 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, 47, 2, 0, 0, 47, 2, 0, 0,119, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0,120, 26,198, 6, 0, 0, 0, 0, +215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 25,198, 6, 0, 0, 0, 0, 0, 0, 16,193, 0, 0,130, 67, + 0, 0,160,192, 0, 0,160, 64, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 16,193, 0, 0, 32, 65, 0, 0, 0, 0, 17, 0, 0, 0, + 18, 0, 0, 0, 75, 1, 0, 0, 18, 0, 0, 0, 86, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 86, 1, 0, 0, + 18, 0, 0, 0, 75, 1, 0, 0,111, 18,131, 58,111, 18,131, 58, 0,124,146, 72, 0, 80, 67, 71, 0, 0, 0, 0, 0, 0, 0, 0, +105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 87, 1, 76, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,217, 0, 0, 0, 47, 2, 0, 0,119, 1, 0, 0,194, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 87, 1, 76, 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, 68, 65, 84, 65,240, 0, 0, 0,232, 27,198, 6, 0, 0, 0, 0, +178, 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, 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, 40, 29,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,112, 0, 0, 0, + 40, 29,198, 6, 0, 0, 0, 0, 37, 1, 0, 0, 1, 0, 0, 0,104, 38,198, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65,160, 0, 0, 0,232, 29,198, 6, 0, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 21,198, 6, 0, 0, 0, 0,200,251,197, 6, 0, 0, 0, 0,232,250,197, 6, 0, 0, 0, 0,152,249,197, 6, 0, 0, 0, 0, + 8,250,197, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 2, 0, 0,240, 4, 0, 0, 93, 1, 0, 0,194, 2, 0, 0, + 8, 8,192, 2,102, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 36,198, 6, 0, 0, 0, 0, +152, 36,198, 6, 0, 0, 0, 0,216, 30,198, 6, 0, 0, 0, 0, 40, 35,198, 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, 68, 65, 84, 65, 40, 1, 0, 0, +216, 30,198, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 72, 32,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,245, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 48, 68, 0, 0, 0, 0, 0, 0,208, 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,191, 2, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,192, 47, 68, 0, 0,200, 65, 0,192, 47, 68, 0, 0,200, 65, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 0, 10, 0,192, 2, 26, 0,192, 2, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 2, 0, 0,240, 4, 0, 0, 93, 1, 0, 0,118, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 2, 26, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, + 72, 32,198, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,184, 33,198, 6, 0, 0, 0, 0,216, 30,198, 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,240, 4, 0, 0,240, 4, 0, 0,119, 1, 0, 0,194, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 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, 68, 65, 84, 65, 40, 1, 0, 0, +184, 33,198, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 40, 35,198, 6, 0, 0, 0, 0, 72, 32,198, 6, 0, 0, 0, 0, + 0, 0,240,195, 0, 0,240, 67, 0, 0,135,195, 0, 0,135, 67,238, 33,143,196,238, 33,143, 68, 0, 0, 7,196, 0, 0, 7, 68, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,191, 2, 0, 0, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 59, 70, 0,128, 59, 70, +172,197, 39, 55, 0, 80,195, 71, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 4, 0, 0,192, 2, 76, 1,192, 2, 76, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 2, 0, 0,240, 4, 0, 0,119, 1, 0, 0,194, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 2, 76, 1, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, + 40, 35,198, 6, 0, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184, 33,198, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 0, 0, 0, 0, 0, 65, + 0, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 75, 1, 0, 0, 18, 0, 0, 0,201, 2, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 18, 0, 0, 0,201, 2, 0, 0, 18, 0, 0, 0, 75, 1, 0, 0, 0, 0, 32, 65, 0, 0, 0, 63, 0,124,146, 72, 0, 0, 0, 66, + 10,215, 35, 60, 0, 0,200, 66,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0,202, 2, 76, 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, 1, 0, 1, 0, 0, 0, 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, 68, 65, 84, 65,240, 0, 0, 0, +152, 36,198, 6, 0, 0, 0, 0,180, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 64, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 83, 67, 0, 0,216, 11, 0, 0,104, 38,198, 6, 0, 0, 0, 0,171, 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, 83, 67, 83, 99,101,110,101, 0, +116, 97,103,101, 0, 97,105,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0,136, 50,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, +248, 64,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 51,198, 6, 0, 0, 0, 0, 56, 52,198, 6, 0, 0, 0, 0, + 88, 51,198, 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, + 1, 0, 0, 0, 1, 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, +168, 52,198, 6, 0, 0, 0, 0,136, 4,230, 0, 73,127, 0, 0, 17, 2, 24, 0, 90, 90, 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,192, 0, 0, 0, 68,172, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 1, 0, 0, 0,250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0,100, 0, 0, 0, + 0, 0, 1, 0, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 2,224, 1, 60, 0, + 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 6, 0, 50, 0,141, 0,128, 7, 56, 4, 8, 0, 8, 0, 24, 0, 17, 0, 0, 0, + 90, 0, 1, 0, 81, 0, 0, 0, 23, 0, 33, 0, 2, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 8, 0, 24, 0, 10, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 56,198, 6, 0, 0, 0, 0,136, 56,198, 6, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 1, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0, 0, 0, 5, 0, 2, 0, 1, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 47,116,109,112, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 5, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0,128, 63, 0, 0,128, 63, +173, 2, 95, 0,154,153,217, 63, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0,180, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 66, 76, 69, 78, 68, 69, 82, 95, 82, 69, 78, 68, 69, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68,172, 0, 0, 0, 0,128, 63,102,166,171, 67, 0, 0,128, 63, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,128,155,194, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +128,230, 81, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,183,159, 6, 0, 0, 0, 0, 1, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 64, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 2,224, 1, 60, 0, + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0,180, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0,205,204,204, 61,154,153,153, 62,205,204, 76, 62,219, 15, 73, 63,102,102,102, 63, + 0, 0, 0, 64,154,153, 25, 63, 0, 0, 64, 65,102,102,166, 63, 0, 0, 0, 65, 0, 0,160, 65, 6, 0, 0, 0, 0, 0,192, 64, + 0, 0,128, 63, 0, 0, 0, 0,205,204, 28, 65, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 1, 0,128, 0, 5, 0,218, 0, 0, 0, + 60, 0, 5, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,195,245, 28,193, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,128, 0, 0, 0,136, 50,198, 6, 0, 0, 0, 0, + 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 40, 0, 0, 0, 88, 51,198, 6, 0, 0, 0, 0,143, 0, 0, 0, 1, 0, 0, 0, +200, 51,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,216, 2,222, 1, +104, 74,198, 6, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0,200, 51,198, 6, 0, 0, 0, 0,143, 0, 0, 0, 1, 0, 0, 0, + 56, 52,198, 6, 0, 0, 0, 0, 88, 51,198, 6, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0,173, 3, 35, 3, +168, 81,198, 6, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 56, 52,198, 6, 0, 0, 0, 0,143, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,200, 51,198, 6, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0,161, 0, 65, 2, +200, 67,198, 6, 0, 0, 0, 0, 68, 65, 84, 65,232, 1, 0, 0,168, 52,198, 6, 0, 0, 0, 0,167, 0, 0, 0, 1, 0, 0, 0, +216, 54,198, 6, 0, 0, 0, 0, 88, 55,198, 6, 0, 0, 0, 0,216, 55,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 1, 0, 1, 0,205,204, 76, 63, 0, 0,180, 66, 9, 0, 1, 0, 0, 0,128, 63,111, 18,131, 58,205,204,204, 61, + 0, 0, 1, 0, 32, 0, 32, 0, 32, 0, 1, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 80, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 5, 0, 5, 0,255,255, + 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 66, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 66, + 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 66, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 66, + 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 66, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 66, + 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 62, 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,128, 63, 10,215, 35, 60,205,204,204, 61, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,250, 0,205,204,204, 61,205,204,204, 61, +102,102,166, 63, 0, 0,192, 63, 0, 0,240, 65, 72,225,122, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 67, 2, 0, 3, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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, 17, 0, 0, 0, 35, 0, 0, 0,204,197,121, 63, 0, 0, 0, 63, 35, 0, 0, 0,204,197,121, 63, + 0, 0, 0, 63, 17, 0, 0, 0, 68, 65, 84, 65, 56, 0, 0, 0,216, 54,198, 6, 0, 0, 0, 0,164, 0, 0, 0, 1, 0, 0, 0, +152,227,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 1, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 0, 0, 0, + 88, 55,198, 6, 0, 0, 0, 0,164, 0, 0, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +200,200,255,128, 1, 0, 0, 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, 68, 65, 84, 65, 96, 0, 0, 0,216, 55,198, 6, 0, 0, 0, 0,162, 0, 0, 0, 1, 0, 0, 0, +136, 84,199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,100,100,128, 1, 0, 0, 0,128, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0,155, 9, 25, 67,190, 23,237, 64, 75, 1,147, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65,120, 0, 0, 0,136, 56,198, 6, 0, 0, 0, 0,149, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 76, 97,121,101,114, 0,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 15, 0, 0, 0, 0, 0, +255,127, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 67, 65, 0, 0,200, 0, 0, 0, 40, 59,198, 6, 0, 0, 0, 0, + 22, 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, 67, 65, 67, 97,109,101,114, 97, 0, 97,109,101,114, 97, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 24, 42,215, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,243,206, 3, 0, 0, 0, 0,136,250,206, 3, 0, 0, 0, 0, 25, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 0, 63,205,204,204, 61, 0, 0,200, 66, 0, 0, 12, 66,161, 14,234, 64, + 0, 0, 0, 63, 0, 0, 0, 66, 0, 0,144, 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, 76, 65, 0, 0, 16, 2, 0, 0, 56, 60,198, 6, 0, 0, 0, 0, + 36, 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, 76, 65, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 8, 0, 0, 0,136, 12,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0,168,182,117, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,152, 0, 0, 0, 24, 42,215, 3, 0, 0, 0, 0,132, 0, 0, 0, 1, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,247,255,239, 65, 0, 0,150, 66, +154,153, 25, 62, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63,152, 62,198, 6, 0, 0, 0, 0, 2, 0, 0, 0, 46, 26,128, 63, + 25, 4,240, 65, 0, 0, 52, 66, 0, 0,128, 63, 0, 0, 64, 64,205,204, 76, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 64, 11, 3, 0, 1, 0, 0, 0, 0, 2, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, +111, 18,131, 58, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61,205,204, 76, 62, 10,215,163, 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, 72, 0, 0, 0, 79, 66, 0, 0,112, 5, 0, 0,168,225,217, 3, 0, 0, 0, 0, -129, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,219,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,136, 64,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 64, 1, 0, 0, +152, 62,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 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,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 2, 0, 1, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,243, 4, 53,191,242, 4, 53, 63,242, 4, 53,191,243, 4, 53, 63, + 40, 64,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 40, 64,198, 6, 0, 0, 0, 0, +117, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 40, 0, 0, 0,136, 64,198, 6, 0, 0, 0, 0, 12, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 87, 79, 0, 0, 24, 2, 0, 0,248, 64,198, 6, 0, 0, 0, 0,142, 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, 87, 79, 87,111,114,108,100, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 99, 80, 61,114, 99, 80, 61,114, 99, 80, 61,199, 54, 36, 60,199, 54, 36, 60,199, 54, 36, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, +205,204, 28, 65, 0, 0, 0, 0, 0, 0, 32, 0,128, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 64, + 0, 0,200, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, + 0, 0,112, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0,128, 63,205,204, 76, 61, + 0, 0, 5, 0, 0, 0, 0, 0, 10,215,163, 59, 0, 0, 0, 0, 0, 0,128, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 0, 0, 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, + 88, 67,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 0, 0, 0, 88, 67,198, 6, 0, 0, 0, 0, + 12, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0,112, 5, 0, 0,200, 67,198, 6, 0, 0, 0, 0, +129, 0, 0, 0, 1, 0, 0, 0,104, 74,198, 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, 79, 66, 67, 97,109,101,114, 97, 0, 97,109,101,114, 97, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,209,217, 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, 40, 59,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 10, 0, 0, 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,154,112,130, 64,183,178,128, 63,112,236,188, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,110,101,239, 64,150, 62,208,192, 78,255,170, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,229,123, 38, 63, 87, 43, 98, 61,229,229,238, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 42,254,141, 63,192, 57, 49, 60, 34,159, 80, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 54,236,148,190, 25,134,116, 63,236, 13, 98,189, 0, 0, 0, 0,221,102, 69,191, 57,174, 76,190, - 34,194, 26, 63, 0, 0, 0, 0, 37,255, 16, 63,241,161, 95, 62,164,111, 75, 63, 0, 0, 0, 0,154,112,130, 64,183,178,128, 63, -112,236,188, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0,222,149, 47, 63, 53, 70, 58, 63,222, 56, 49,188, 0, 0, 0, 0, 86,126,162,190,227,251,159, 62, + 55, 53,101, 63, 0, 0, 0, 0, 7,165, 39, 63,149, 84, 28,191, 51,247,227, 62, 0, 0, 0, 0,110,101,239, 64,150, 62,208,192, + 78,255,170, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 1, 0,128, 50, 0, 0, 0,179, 0, 0, 0, 0, 1, 0,128, 50, 1, 0,128, 63, - 1, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 1, 0, 0, 39, 1, 0, 0, 52, - 1, 0,128, 39, 0, 0,128, 63, 54,236,148,190,221,102, 69,191, 38,255, 16, 63, 0, 0, 0, 0, 24,134,116, 63, 57,174, 76,190, -239,161, 95, 62, 0, 0, 0, 0,237, 13, 98,189, 35,194, 26, 63,166,111, 75, 63, 0, 0, 0, 0,209, 19, 13, 63,241, 65,102,190, - 10, 10,231,192, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 1, 0,128, 63, 1, 0,128, 51, 1, 0, 0,179, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0,128, 63, + 1, 0,128, 51, 0, 0, 0, 0, 2, 0, 0,179, 2, 0, 0,167, 1, 0,128, 63, 0, 0, 0, 0, 1, 0, 0, 53, 1, 0, 0, 41, + 1, 0,128,168, 0, 0,128, 63,221,149, 47, 63, 86,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63,225,251,159, 62, +149, 84, 28,191, 0, 0, 0, 0,192, 56, 49,188, 55, 53,101, 63, 52,247,227, 62, 0, 0, 0, 0, 90, 38,173,190, 0,222,192,190, +152, 9, 52,193, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 1, 0, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 56,180,150,201, 0, 0,128, 63, -169, 19,208, 60, 0, 0,128, 63,205,204,204, 62,229,208, 34, 62, 0, 0, 0, 0,143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 5, 0, 1, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, +187,225, 16, 63, 0, 0,128, 63,205,204,204, 62,237, 54, 32, 63, 0, 0, 0, 0,143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 1, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,231,217, 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,136, 73,198, 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, 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, 68, 65, 84, 65,152, 0, 0, 0, -200,231,217, 3, 0, 0, 0, 0,132, 0, 0, 0, 1, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +136, 73,198, 6, 0, 0, 0, 0,132, 0, 0, 0, 1, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61,205,204, 76, 62, 10,215,163, 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, 2, 0, 0, 0, 77, 65, 0, 0,128, 3, 0, 0,152, 7,218, 3, 0, 0, 0, 0, 39, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 77, 65, 77, 97,116,101,114,105, 97,108, 0, 0, 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, 0, 0, 79, 66, 0, 0,112, 5, 0, 0,104, 74,198, 6, 0, 0, 0, 0,129, 0, 0, 0, 1, 0, 0, 0, +168, 81,198, 6, 0, 0, 0, 0,200, 67,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 66, 67,117, 98,101, 0,112,104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 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,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63,205,204, 76, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 10,215, 35, 60, 0, 0, 0, 0, - 0, 0, 8, 0, 1, 0, 50, 0,205,204, 76, 62, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 16, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 63, 0, 0, 0, 0, 0, 0,160, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 2, 0, 2, 0, 50, 0, 0, 6, 0, 0,128, 63, 0, 0,128, 63, 18, 0, 18, 0, 10,215,163, 59, 10,215,163, 59, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 4, 0, 67, 0, 64, 3, 67, 0, 64, 3, 1, 0, 4, 0, 12, 0, 4, 0, 0, 0, 0, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 1, 0, 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, 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,128, 63, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0,128, 64, 0, 0, 0, 63,205,204,204, 61, 0, 0, 0, 63,205,204,204, 61,205,204,204, 61, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,104,112,223, 0, 73,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, + 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, + 10, 0, 0, 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, 40, 80,198, 6, 0, 0, 0, 0,120, 80,198, 6, 0, 0, 0, 0, 1, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 68, 0, 0, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 56,180,150,201, 0, 0,128, 63,169, 19,208, 60, 0, 0,128, 63, +205,204,204, 62,229,208, 34, 62, 0, 0, 0, 0,143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 5, 0, 1, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 64, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 80,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 63,225, 0, 73,127, 0, 0, +248, 81,225, 0, 73,127, 0, 0, 25, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 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, 68, 65, 84, 65, 8, 0, 0, 0, 40, 80,198, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0,120, 80,198, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,152, 0, 0, 0,200, 80,198, 6, 0, 0, 0, 0,132, 0, 0, 0, + 1, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61, +205,204, 76, 62, 10,215,163, 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, 72, 0, 0, 0, 79, 66, 0, 0, +112, 5, 0, 0,168, 81,198, 6, 0, 0, 0, 0,129, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 74,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 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, 56, 60,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 10, 0, 0, 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,154,112,130, 64,183,178,128, 63,112,236,188, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,229,123, 38, 63, + 87, 43, 98, 61,229,229,238, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,236,148,190, 25,134,116, 63,236, 13, 98,189, + 0, 0, 0, 0,221,102, 69,191, 57,174, 76,190, 34,194, 26, 63, 0, 0, 0, 0, 37,255, 16, 63,241,161, 95, 62,164,111, 75, 63, + 0, 0, 0, 0,154,112,130, 64,183,178,128, 63,112,236,188, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 1, 0,128, 50, 0, 0, 0,179, + 0, 0, 0, 0, 1, 0,128, 50, 1, 0,128, 63, 1, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 1, 0, 0, 39, 1, 0, 0, 52, 1, 0,128, 39, 0, 0,128, 63, 54,236,148,190,221,102, 69,191, 38,255, 16, 63, + 0, 0, 0, 0, 24,134,116, 63, 57,174, 76,190,239,161, 95, 62, 0, 0, 0, 0,237, 13, 98,189, 35,194, 26, 63,166,111, 75, 63, + 0, 0, 0, 0,209, 19, 13, 63,241, 65,102,190, 10, 10,231,192, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 5, 0, 1, 0, 0, 0, 68, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, + 0, 0, 0, 0, 56,180,150,201, 0, 0,128, 63,169, 19,208, 60, 0, 0,128, 63,205,204,204, 62,229,208, 34, 62, 0, 0, 0, 0, +143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 5, 0, 1, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63,152, 11,218, 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, 64, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,104, 87,198, 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,152,120,216, 3, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,111,148, 26, 63, -111,148, 26, 63,111,148, 26, 63,205,204, 76, 61,205,204,204, 61,102,102,166, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 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, - 68, 65, 84, 65, 56, 1, 0, 0,152, 11,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,216, 29,218, 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, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 68, 65, 84, 65,152, 0, 0, 0,104, 87,198, 6, 0, 0, 0, 0,132, 0, 0, 0, 1, 0, 0, 0, 0,192, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61,205,204, 76, 62, 10,215,163, 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, 2, 0, 0, 0, 77, 65, 0, 0,128, 3, 0, 0, 72, 88,198, 6, + 0, 0, 0, 0, 39, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 90, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 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,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63,205,204, 76, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 40, 0, 0, 0,152,120,216, 3, 0, 0, 0, 0, - 12, 0, 0, 0, 1, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 53, 0, 53, 0, - 88, 13,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 16, 0, 0, 88, 13,218, 3, 0, 0, 0, 0, - 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, 2, 2, 2, 51, 2, 2, 2, 51, - 6, 6, 6,153, 6, 6, 6,153, 6, 6, 6,153, 4, 4, 4,102, 3, 3, 3,102, 2, 2, 2, 51, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 3, 3, 51, 8, 8, 8,153, 11, 11, 11,204, 13, 13, 13,255, 12, 12, 12,255, - 12, 12, 12,255, 11, 11, 11,255, 10, 10, 10,255, 10, 10, 10,255, 9, 9, 9,255, 9, 9, 9,255, 9, 9, 9,255, 4, 4, 4,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, 3, 3, 3, 51, 10, 10, 10,153, 18, 18, 18,255, 20, 20, 20,255, 22, 22, 22,255, 23, 23, 23,255, 22, 22, 22,255, - 20, 20, 20,255, 19, 19, 19,255, 16, 16, 16,255, 14, 14, 14,255, 11, 11, 11,255, 10, 10, 10,255, 9, 9, 9,255, 9, 9, 9,255, - 9, 9, 9,255, 8, 8, 8,204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 7, 7,102, 19, 19, 19,204, 27, 27, 27,255, 31, 31, 31,255, 32, 32, 32,255, 33, 33, 33,255, 33, 33, 33,255, 31, 31, 31,255, - 30, 30, 30,255, 27, 27, 27,255, 25, 25, 25,255, 22, 22, 22,255, 19, 19, 19,255, 16, 16, 16,255, 12, 12, 12,255, 10, 10, 10,255, - 10, 10, 10,255, 10, 10, 10,255, 10, 10, 10,255, 4, 4, 4,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, 13, 13, 13,153, - 29, 29, 29,255, 37, 37, 37,255, 40, 40, 40,255, 42, 42, 42,255, 42, 42, 42,255, 43, 43, 43,255, 41, 41, 41,255, 40, 40, 40,255, - 38, 38, 38,255, 36, 36, 36,255, 33, 33, 33,255, 30, 30, 30,255, 27, 27, 27,255, 24, 24, 24,255, 20, 20, 20,255, 16, 16, 16,255, - 12, 12, 12,255, 10, 10, 10,255, 10, 10, 10,255, 10, 10, 10,255, 7, 7, 7,153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13,102, 37, 37, 37,255, - 44, 44, 44,255, 48, 48, 48,255, 50, 50, 50,255, 51, 51, 51,255, 51, 51, 51,255, 50, 50, 50,255, 49, 49, 49,255, 48, 48, 48,255, - 45, 45, 45,255, 43, 43, 43,255, 41, 41, 41,255, 37, 37, 37,255, 34, 34, 34,255, 31, 31, 31,255, 28, 28, 28,255, 24, 24, 24,255, - 20, 20, 20,255, 15, 15, 15,255, 11, 11, 11,255, 10, 10, 10,255, 11, 11, 11,255, 7, 7, 7,153, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13,102, 41, 41, 41,255, 50, 50, 50,255, - 54, 54, 54,255, 57, 57, 57,255, 58, 58, 58,255, 59, 59, 59,255, 59, 59, 59,255, 58, 58, 58,255, 57, 57, 57,255, 55, 55, 55,255, - 53, 53, 53,255, 51, 51, 51,255, 48, 48, 48,255, 45, 45, 45,255, 41, 41, 41,255, 38, 38, 38,255, 35, 35, 35,255, 31, 31, 31,255, - 27, 27, 27,255, 23, 23, 23,255, 17, 17, 17,255, 12, 12, 12,255, 11, 11, 11,255, 11, 11, 11,255, 5, 5, 5,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, 36, 36, 36,204, 53, 53, 53,255, 59, 59, 59,255, - 63, 63, 63,255, 65, 65, 65,255, 66, 66, 66,255, 66, 66, 66,255, 66, 66, 66,255, 65, 65, 65,255, 64, 64, 64,255, 62, 62, 62,255, - 60, 60, 60,255, 57, 57, 57,255, 54, 54, 54,255, 51, 51, 51,255, 48, 48, 48,255, 44, 44, 44,255, 41, 41, 41,255, 37, 37, 37,255, - 33, 33, 33,255, 29, 29, 29,255, 24, 24, 24,255, 19, 19, 19,255, 13, 13, 13,255, 11, 11, 11,255, 12, 12, 12,255, 3, 3, 3, 51, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19,102, 56, 56, 56,255, 64, 64, 64,255, 68, 68, 68,255, - 71, 71, 71,255, 73, 73, 73,255, 74, 74, 74,255, 74, 74, 74,255, 73, 73, 73,255, 72, 72, 72,255, 71, 71, 71,255, 69, 69, 69,255, - 67, 67, 67,255, 64, 64, 64,255, 61, 61, 61,255, 58, 58, 58,255, 54, 54, 54,255, 50, 50, 50,255, 47, 47, 47,255, 43, 43, 43,255, - 39, 39, 39,255, 34, 34, 34,255, 30, 30, 30,255, 25, 25, 25,255, 19, 19, 19,255, 13, 13, 13,255, 12, 12, 12,255, 10, 10, 10,204, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54,255, 66, 66, 66,255, 72, 72, 72,255, 77, 77, 77,255, - 79, 79, 79,255, 81, 81, 81,255, 81, 81, 81,255, 81, 81, 81,255, 80, 80, 80,255, 79, 79, 79,255, 77, 77, 77,255, 75, 75, 75,255, - 73, 73, 73,255, 70, 70, 70,255, 67, 67, 67,255, 63, 63, 63,255, 60, 60, 60,255, 56, 56, 56,255, 52, 52, 52,255, 49, 49, 49,255, - 44, 44, 44,255, 40, 40, 40,255, 35, 35, 35,255, 30, 30, 30,255, 24, 24, 24,255, 18, 18, 18,255, 12, 12, 12,255, 12, 12, 12,255, - 6, 6, 6,102, 0, 0, 0, 0, 0, 0, 0, 0, 22, 22, 22,102, 67, 67, 67,255, 76, 76, 76,255, 81, 81, 81,255, 84, 84, 84,255, - 87, 87, 87,255, 88, 88, 88,255, 88, 88, 88,255, 88, 88, 88,255, 87, 87, 87,255, 86, 86, 86,255, 84, 84, 84,255, 82, 82, 82,255, - 79, 79, 79,255, 76, 76, 76,255, 73, 73, 73,255, 69, 69, 69,255, 65, 65, 65,255, 62, 62, 62,255, 58, 58, 58,255, 54, 54, 54,255, - 49, 49, 49,255, 45, 45, 45,255, 40, 40, 40,255, 35, 35, 35,255, 29, 29, 29,255, 23, 23, 23,255, 16, 16, 16,255, 12, 12, 12,255, - 12, 12, 12,204, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49,204, 76, 76, 76,255, 84, 84, 84,255, 89, 89, 89,255, 92, 92, 92,255, - 94, 94, 94,255, 95, 95, 95,255, 95, 95, 95,255, 95, 95, 95,255, 94, 94, 94,255, 93, 93, 93,255, 91, 91, 91,255, 88, 88, 88,255, - 85, 85, 85,255, 82, 82, 82,255, 79, 79, 79,255, 75, 75, 75,255, 71, 71, 71,255, 67, 67, 67,255, 63, 63, 63,255, 59, 59, 59,255, - 55, 55, 55,255, 50, 50, 50,255, 45, 45, 45,255, 40, 40, 40,255, 34, 34, 34,255, 28, 28, 28,255, 21, 21, 21,255, 13, 13, 13,255, - 14, 14, 14,255, 0, 0, 0, 0, 14, 14, 14,102, 70, 70, 70,255, 85, 85, 85,255, 92, 92, 92,255, 97, 97, 97,255,100,100,100,255, -102,102,102,255,102,102,102,255,103,103,103,255,102,102,102,255,101,101,101,255, 99, 99, 99,255, 97, 97, 97,255, 94, 94, 94,255, - 91, 91, 91,255, 88, 88, 88,255, 84, 84, 84,255, 81, 81, 81,255, 77, 77, 77,255, 72, 72, 72,255, 68, 68, 68,255, 64, 64, 64,255, - 59, 59, 59,255, 55, 55, 55,255, 50, 50, 50,255, 44, 44, 44,255, 39, 39, 39,255, 32, 32, 32,255, 25, 25, 25,255, 17, 17, 17,255, - 13, 13, 13,255, 7, 7, 7,102, 24, 24, 24,102, 80, 80, 80,255, 93, 93, 93,255,100,100,100,255,104,104,104,255,107,107,107,255, -109,109,109,255,109,109,109,255,109,109,109,255,109,109,109,255,107,107,107,255,106,106,106,255,103,103,103,255,100,100,100,255, - 97, 97, 97,255, 94, 94, 94,255, 90, 90, 90,255, 86, 86, 86,255, 82, 82, 82,255, 77, 77, 77,255, 73, 73, 73,255, 69, 69, 69,255, - 64, 64, 64,255, 59, 59, 59,255, 54, 54, 54,255, 49, 49, 49,255, 43, 43, 43,255, 36, 36, 36,255, 29, 29, 29,255, 21, 21, 21,255, - 14, 14, 14,255, 10, 10, 10,153, 29, 29, 29,102, 89, 89, 89,255,100,100,100,255,107,107,107,255,112,112,112,255,114,114,114,255, -116,116,116,255,116,116,116,255,116,116,116,255,115,115,115,255,114,114,114,255,112,112,112,255,110,110,110,255,107,107,107,255, -104,104,104,255,100,100,100,255, 96, 96, 96,255, 92, 92, 92,255, 87, 87, 87,255, 83, 83, 83,255, 78, 78, 78,255, 73, 73, 73,255, - 68, 68, 68,255, 63, 63, 63,255, 58, 58, 58,255, 52, 52, 52,255, 46, 46, 46,255, 40, 40, 40,255, 33, 33, 33,255, 24, 24, 24,255, - 17, 17, 17,255, 13, 13, 13,204, 46, 46, 46,153, 95, 95, 95,255,107,107,107,255,114,114,114,255,118,118,118,255,121,121,121,255, -122,122,122,255,123,123,123,255,123,123,123,255,122,122,122,255,122,122,122,255,120,120,120,255,118,118,118,255,114,114,114,255, -110,110,110,255,106,106,106,255,101,101,101,255, 97, 97, 97,255, 92, 92, 92,255, 87, 87, 87,255, 83, 83, 83,255, 78, 78, 78,255, - 73, 73, 73,255, 68, 68, 68,255, 62, 62, 62,255, 56, 56, 56,255, 50, 50, 50,255, 44, 44, 44,255, 36, 36, 36,255, 28, 28, 28,255, - 19, 19, 19,255, 12, 12, 12,204, 47, 47, 47,153,101,101,101,255,113,113,113,255,120,120,120,255,125,125,125,255,127,127,127,255, -129,129,129,255,130,130,130,255,130,130,130,255,131,131,131,255,131,131,131,255,131,131,131,255,129,129,129,255,125,125,125,255, -120,120,120,255,113,113,113,255,108,108,108,255,103,103,103,255, 97, 97, 97,255, 92, 92, 92,255, 87, 87, 87,255, 82, 82, 82,255, - 77, 77, 77,255, 72, 72, 72,255, 66, 66, 66,255, 60, 60, 60,255, 54, 54, 54,255, 47, 47, 47,255, 39, 39, 39,255, 31, 31, 31,255, - 22, 22, 22,255, 12, 12, 12,204, 48, 48, 48,153,106,106,106,255,118,118,118,255,126,126,126,255,131,131,131,255,134,134,134,255, -135,135,135,255,137,137,137,255,138,138,138,255,142,142,142,255,147,147,147,255,149,149,149,255,148,148,148,255,142,142,142,255, -133,133,133,255,124,124,124,255,115,115,115,255,108,108,108,255,102,102,102,255, 97, 97, 97,255, 92, 92, 92,255, 87, 87, 87,255, - 81, 81, 81,255, 75, 75, 75,255, 69, 69, 69,255, 63, 63, 63,255, 57, 57, 57,255, 49, 49, 49,255, 42, 42, 42,255, 33, 33, 33,255, - 24, 24, 24,255, 9, 9, 9,153, 32, 32, 32,102,109,109,109,255,123,123,123,255,131,131,131,255,136,136,136,255,140,140,140,255, -142,142,142,255,144,144,144,255,148,148,148,255,156,156,156,255,168,168,168,255,176,176,176,255,177,177,177,255,168,168,168,255, -153,153,153,255,137,137,137,255,124,124,124,255,114,114,114,255,107,107,107,255,101,101,101,255, 96, 96, 96,255, 90, 90, 90,255, - 85, 85, 85,255, 79, 79, 79,255, 72, 72, 72,255, 66, 66, 66,255, 59, 59, 59,255, 52, 52, 52,255, 44, 44, 44,255, 35, 35, 35,255, - 26, 26, 26,255, 10, 10, 10,153, 17, 17, 17, 51,110,110,110,255,127,127,127,255,136,136,136,255,142,142,142,255,145,145,145,255, -148,148,148,255,151,151,151,255,159,159,159,255,174,174,174,255,195,195,195,255,212,212,212,255,216,216,216,255,204,204,204,255, -179,179,179,255,154,154,154,255,135,135,135,255,121,121,121,255,112,112,112,255,106,106,106,255, 99, 99, 99,255, 94, 94, 94,255, - 88, 88, 88,255, 82, 82, 82,255, 76, 76, 76,255, 69, 69, 69,255, 62, 62, 62,255, 54, 54, 54,255, 46, 46, 46,255, 37, 37, 37,255, - 26, 26, 26,255, 6, 6, 6,102, 0, 0, 0, 0,107,107,107,255,130,130,130,255,140,140,140,255,146,146,146,255,150,150,150,255, -153,153,153,255,158,158,158,255,169,169,169,255,191,191,191,255,219,219,219,255,246,246,246,255,254,254,254,255,237,237,237,255, -204,204,204,255,170,170,170,255,145,145,145,255,127,127,127,255,117,117,117,255,110,110,110,255,103,103,103,255, 97, 97, 97,255, - 91, 91, 91,255, 85, 85, 85,255, 78, 78, 78,255, 71, 71, 71,255, 64, 64, 64,255, 55, 55, 55,255, 47, 47, 47,255, 37, 37, 37,255, - 25, 25, 25,255, 3, 3, 3, 51, 0, 0, 0, 0, 65, 65, 65,153,129,129,129,255,142,142,142,255,149,149,149,255,154,154,154,255, -158,158,158,255,163,163,163,255,176,176,176,255,199,199,199,255,232,232,232,255,255,255,255,255,255,255,255,255,255,255,255,255, -220,220,220,255,181,181,181,255,151,151,151,255,132,132,132,255,121,121,121,255,113,113,113,255,106,106,106,255,100,100,100,255, - 94, 94, 94,255, 87, 87, 87,255, 80, 80, 80,255, 73, 73, 73,255, 65, 65, 65,255, 57, 57, 57,255, 48, 48, 48,255, 38, 38, 38,255, - 16, 16, 16,153, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 51,127,127,127,255,143,143,143,255,152,152,152,255,157,157,157,255, -161,161,161,255,165,165,165,255,177,177,177,255,198,198,198,255,227,227,227,255,253,253,253,255,255,255,255,255,250,250,250,255, -217,217,217,255,181,181,181,255,153,153,153,255,135,135,135,255,124,124,124,255,117,117,117,255,110,110,110,255,103,103,103,255, - 96, 96, 96,255, 89, 89, 89,255, 82, 82, 82,255, 74, 74, 74,255, 66, 66, 66,255, 57, 57, 57,255, 48, 48, 48,255, 35, 35, 35,255, - 10, 10, 10,153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93,204,141,141,141,255,153,153,153,255,159,159,159,255, -163,163,163,255,167,167,167,255,174,174,174,255,188,188,188,255,209,209,209,255,228,228,228,255,234,234,234,255,224,224,224,255, -200,200,200,255,173,173,173,255,151,151,151,255,136,136,136,255,127,127,127,255,119,119,119,255,112,112,112,255,105,105,105,255, - 98, 98, 98,255, 90, 90, 90,255, 83, 83, 83,255, 75, 75, 75,255, 66, 66, 66,255, 57, 57, 57,255, 46, 46, 46,255, 24, 24, 24,204, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 51,134,134,134,255,151,151,151,255,160,160,160,255, -164,164,164,255,167,167,167,255,171,171,171,255,178,178,178,255,189,189,189,255,200,200,200,255,202,202,202,255,195,195,195,255, -180,180,180,255,163,163,163,255,148,148,148,255,137,137,137,255,129,129,129,255,121,121,121,255,114,114,114,255,107,107,107,255, - 99, 99, 99,255, 91, 91, 91,255, 83, 83, 83,255, 74, 74, 74,255, 65, 65, 65,255, 55, 55, 55,255, 41, 41, 41,255, 7, 7, 7, 51, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49,102,145,145,145,255,157,157,157,255, -164,164,164,255,167,167,167,255,170,170,170,255,172,172,172,255,176,176,176,255,180,180,180,255,179,179,179,255,174,174,174,255, -165,165,165,255,155,155,155,255,145,145,145,255,137,137,137,255,130,130,130,255,122,122,122,255,115,115,115,255,107,107,107,255, - 99, 99, 99,255, 91, 91, 91,255, 82, 82, 82,255, 73, 73, 73,255, 63, 63, 63,255, 50, 50, 50,255, 22, 22, 22,153, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 78, 78,153,149,149,149,255, -160,160,160,255,166,166,166,255,168,168,168,255,169,169,169,255,170,170,170,255,169,169,169,255,167,167,167,255,164,164,164,255, -158,158,158,255,151,151,151,255,144,144,144,255,137,137,137,255,130,130,130,255,123,123,123,255,115,115,115,255,106,106,106,255, - 98, 98, 98,255, 89, 89, 89,255, 80, 80, 80,255, 70, 70, 70,255, 58, 58, 58,255, 27, 27, 27,153, 3, 3, 3, 51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80,153, -150,150,150,255,160,160,160,255,165,165,165,255,167,167,167,255,167,167,167,255,166,166,166,255,163,163,163,255,160,160,160,255, -155,155,155,255,149,149,149,255,143,143,143,255,137,137,137,255,129,129,129,255,121,121,121,255,113,113,113,255,105,105,105,255, - 96, 96, 96,255, 86, 86, 86,255, 76, 76, 76,255, 63, 63, 63,255, 38, 38, 38,204, 7, 7, 7, 51, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 10,215, 35, 60, 0, 0, 0, 0, 0, 0, 8, 0, 1, 0, 50, 0,205,204, 76, 62, 0, 0,128, 63, 0, 0,128, 63, +205,204, 76, 62, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 63, 0, 0, 0, 0, + 0, 0,160, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 2, 0, 2, 0, 50, 0, 0, 6, 0, 0,128, 63, 0, 0,128, 63, + 18, 0, 18, 0, 10,215,163, 59, 10,215,163, 59, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 4, 0, 67, 0, 64, 3, 67, 0, 64, 3, + 1, 0, 4, 0, 12, 0, 4, 0, 0, 0, 0, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0,128, 64, 0, 0, 0, 63,205,204,204, 61, + 0, 0, 0, 63,205,204,204, 61,205,204,204, 61, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 24, 92,198, 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,152, 93,198, 6, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63,111,148, 26, 63,111,148, 26, 63,111,148, 26, 63,205,204, 76, 61,205,204,204, 61,102,102,166, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 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, 68, 65, 84, 65, 56, 1, 0, 0, 24, 92,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,110,198, 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, 1, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 40, 0, 0, 0,152, 93,198, 6, 0, 0, 0, 0, 12, 0, 0, 0, 1, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 53, 0, 53, 0, 8, 94,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 0, 16, 0, 0, 8, 94,198, 6, 0, 0, 0, 0, 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, 2, 2, 2, 51, 2, 2, 2, 51, 6, 6, 6,153, 6, 6, 6,153, 6, 6, 6,153, 4, 4, 4,102, 3, 3, 3,102, + 2, 2, 2, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 3, 3, 51, 8, 8, 8,153, + 11, 11, 11,204, 13, 13, 13,255, 12, 12, 12,255, 12, 12, 12,255, 11, 11, 11,255, 10, 10, 10,255, 10, 10, 10,255, 9, 9, 9,255, + 9, 9, 9,255, 9, 9, 9,255, 4, 4, 4,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, 3, 3, 3, 51, 10, 10, 10,153, 18, 18, 18,255, 20, 20, 20,255, + 22, 22, 22,255, 23, 23, 23,255, 22, 22, 22,255, 20, 20, 20,255, 19, 19, 19,255, 16, 16, 16,255, 14, 14, 14,255, 11, 11, 11,255, + 10, 10, 10,255, 9, 9, 9,255, 9, 9, 9,255, 9, 9, 9,255, 8, 8, 8,204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7,102, 19, 19, 19,204, 27, 27, 27,255, 31, 31, 31,255, 32, 32, 32,255, + 33, 33, 33,255, 33, 33, 33,255, 31, 31, 31,255, 30, 30, 30,255, 27, 27, 27,255, 25, 25, 25,255, 22, 22, 22,255, 19, 19, 19,255, + 16, 16, 16,255, 12, 12, 12,255, 10, 10, 10,255, 10, 10, 10,255, 10, 10, 10,255, 10, 10, 10,255, 4, 4, 4,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, 13, 13, 13,153, 29, 29, 29,255, 37, 37, 37,255, 40, 40, 40,255, 42, 42, 42,255, 42, 42, 42,255, + 43, 43, 43,255, 41, 41, 41,255, 40, 40, 40,255, 38, 38, 38,255, 36, 36, 36,255, 33, 33, 33,255, 30, 30, 30,255, 27, 27, 27,255, + 24, 24, 24,255, 20, 20, 20,255, 16, 16, 16,255, 12, 12, 12,255, 10, 10, 10,255, 10, 10, 10,255, 10, 10, 10,255, 7, 7, 7,153, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 13, 13,102, 37, 37, 37,255, 44, 44, 44,255, 48, 48, 48,255, 50, 50, 50,255, 51, 51, 51,255, 51, 51, 51,255, + 50, 50, 50,255, 49, 49, 49,255, 48, 48, 48,255, 45, 45, 45,255, 43, 43, 43,255, 41, 41, 41,255, 37, 37, 37,255, 34, 34, 34,255, + 31, 31, 31,255, 28, 28, 28,255, 24, 24, 24,255, 20, 20, 20,255, 15, 15, 15,255, 11, 11, 11,255, 10, 10, 10,255, 11, 11, 11,255, + 7, 7, 7,153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13,102, 41, 41, 41,255, 50, 50, 50,255, 54, 54, 54,255, 57, 57, 57,255, 58, 58, 58,255, 59, 59, 59,255, 59, 59, 59,255, + 58, 58, 58,255, 57, 57, 57,255, 55, 55, 55,255, 53, 53, 53,255, 51, 51, 51,255, 48, 48, 48,255, 45, 45, 45,255, 41, 41, 41,255, + 38, 38, 38,255, 35, 35, 35,255, 31, 31, 31,255, 27, 27, 27,255, 23, 23, 23,255, 17, 17, 17,255, 12, 12, 12,255, 11, 11, 11,255, + 11, 11, 11,255, 5, 5, 5,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, + 36, 36, 36,204, 53, 53, 53,255, 59, 59, 59,255, 63, 63, 63,255, 65, 65, 65,255, 66, 66, 66,255, 66, 66, 66,255, 66, 66, 66,255, + 65, 65, 65,255, 64, 64, 64,255, 62, 62, 62,255, 60, 60, 60,255, 57, 57, 57,255, 54, 54, 54,255, 51, 51, 51,255, 48, 48, 48,255, + 44, 44, 44,255, 41, 41, 41,255, 37, 37, 37,255, 33, 33, 33,255, 29, 29, 29,255, 24, 24, 24,255, 19, 19, 19,255, 13, 13, 13,255, + 11, 11, 11,255, 12, 12, 12,255, 3, 3, 3, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19,102, + 56, 56, 56,255, 64, 64, 64,255, 68, 68, 68,255, 71, 71, 71,255, 73, 73, 73,255, 74, 74, 74,255, 74, 74, 74,255, 73, 73, 73,255, + 72, 72, 72,255, 71, 71, 71,255, 69, 69, 69,255, 67, 67, 67,255, 64, 64, 64,255, 61, 61, 61,255, 58, 58, 58,255, 54, 54, 54,255, + 50, 50, 50,255, 47, 47, 47,255, 43, 43, 43,255, 39, 39, 39,255, 34, 34, 34,255, 30, 30, 30,255, 25, 25, 25,255, 19, 19, 19,255, + 13, 13, 13,255, 12, 12, 12,255, 10, 10, 10,204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54,255, + 66, 66, 66,255, 72, 72, 72,255, 77, 77, 77,255, 79, 79, 79,255, 81, 81, 81,255, 81, 81, 81,255, 81, 81, 81,255, 80, 80, 80,255, + 79, 79, 79,255, 77, 77, 77,255, 75, 75, 75,255, 73, 73, 73,255, 70, 70, 70,255, 67, 67, 67,255, 63, 63, 63,255, 60, 60, 60,255, + 56, 56, 56,255, 52, 52, 52,255, 49, 49, 49,255, 44, 44, 44,255, 40, 40, 40,255, 35, 35, 35,255, 30, 30, 30,255, 24, 24, 24,255, + 18, 18, 18,255, 12, 12, 12,255, 12, 12, 12,255, 6, 6, 6,102, 0, 0, 0, 0, 0, 0, 0, 0, 22, 22, 22,102, 67, 67, 67,255, + 76, 76, 76,255, 81, 81, 81,255, 84, 84, 84,255, 87, 87, 87,255, 88, 88, 88,255, 88, 88, 88,255, 88, 88, 88,255, 87, 87, 87,255, + 86, 86, 86,255, 84, 84, 84,255, 82, 82, 82,255, 79, 79, 79,255, 76, 76, 76,255, 73, 73, 73,255, 69, 69, 69,255, 65, 65, 65,255, + 62, 62, 62,255, 58, 58, 58,255, 54, 54, 54,255, 49, 49, 49,255, 45, 45, 45,255, 40, 40, 40,255, 35, 35, 35,255, 29, 29, 29,255, + 23, 23, 23,255, 16, 16, 16,255, 12, 12, 12,255, 12, 12, 12,204, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49,204, 76, 76, 76,255, + 84, 84, 84,255, 89, 89, 89,255, 92, 92, 92,255, 94, 94, 94,255, 95, 95, 95,255, 95, 95, 95,255, 95, 95, 95,255, 94, 94, 94,255, + 93, 93, 93,255, 91, 91, 91,255, 88, 88, 88,255, 85, 85, 85,255, 82, 82, 82,255, 79, 79, 79,255, 75, 75, 75,255, 71, 71, 71,255, + 67, 67, 67,255, 63, 63, 63,255, 59, 59, 59,255, 55, 55, 55,255, 50, 50, 50,255, 45, 45, 45,255, 40, 40, 40,255, 34, 34, 34,255, + 28, 28, 28,255, 21, 21, 21,255, 13, 13, 13,255, 14, 14, 14,255, 0, 0, 0, 0, 14, 14, 14,102, 70, 70, 70,255, 85, 85, 85,255, + 92, 92, 92,255, 97, 97, 97,255,100,100,100,255,102,102,102,255,102,102,102,255,103,103,103,255,102,102,102,255,101,101,101,255, + 99, 99, 99,255, 97, 97, 97,255, 94, 94, 94,255, 91, 91, 91,255, 88, 88, 88,255, 84, 84, 84,255, 81, 81, 81,255, 77, 77, 77,255, + 72, 72, 72,255, 68, 68, 68,255, 64, 64, 64,255, 59, 59, 59,255, 55, 55, 55,255, 50, 50, 50,255, 44, 44, 44,255, 39, 39, 39,255, + 32, 32, 32,255, 25, 25, 25,255, 17, 17, 17,255, 13, 13, 13,255, 7, 7, 7,102, 24, 24, 24,102, 80, 80, 80,255, 93, 93, 93,255, +100,100,100,255,104,104,104,255,107,107,107,255,109,109,109,255,109,109,109,255,109,109,109,255,109,109,109,255,107,107,107,255, +106,106,106,255,103,103,103,255,100,100,100,255, 97, 97, 97,255, 94, 94, 94,255, 90, 90, 90,255, 86, 86, 86,255, 82, 82, 82,255, + 77, 77, 77,255, 73, 73, 73,255, 69, 69, 69,255, 64, 64, 64,255, 59, 59, 59,255, 54, 54, 54,255, 49, 49, 49,255, 43, 43, 43,255, + 36, 36, 36,255, 29, 29, 29,255, 21, 21, 21,255, 14, 14, 14,255, 10, 10, 10,153, 29, 29, 29,102, 89, 89, 89,255,100,100,100,255, +107,107,107,255,112,112,112,255,114,114,114,255,116,116,116,255,116,116,116,255,116,116,116,255,115,115,115,255,114,114,114,255, +112,112,112,255,110,110,110,255,107,107,107,255,104,104,104,255,100,100,100,255, 96, 96, 96,255, 92, 92, 92,255, 87, 87, 87,255, + 83, 83, 83,255, 78, 78, 78,255, 73, 73, 73,255, 68, 68, 68,255, 63, 63, 63,255, 58, 58, 58,255, 52, 52, 52,255, 46, 46, 46,255, + 40, 40, 40,255, 33, 33, 33,255, 24, 24, 24,255, 17, 17, 17,255, 13, 13, 13,204, 46, 46, 46,153, 95, 95, 95,255,107,107,107,255, +114,114,114,255,118,118,118,255,121,121,121,255,122,122,122,255,123,123,123,255,123,123,123,255,122,122,122,255,122,122,122,255, +120,120,120,255,118,118,118,255,114,114,114,255,110,110,110,255,106,106,106,255,101,101,101,255, 97, 97, 97,255, 92, 92, 92,255, + 87, 87, 87,255, 83, 83, 83,255, 78, 78, 78,255, 73, 73, 73,255, 68, 68, 68,255, 62, 62, 62,255, 56, 56, 56,255, 50, 50, 50,255, + 44, 44, 44,255, 36, 36, 36,255, 28, 28, 28,255, 19, 19, 19,255, 12, 12, 12,204, 47, 47, 47,153,101,101,101,255,113,113,113,255, +120,120,120,255,125,125,125,255,127,127,127,255,129,129,129,255,130,130,130,255,130,130,130,255,131,131,131,255,131,131,131,255, +131,131,131,255,129,129,129,255,125,125,125,255,120,120,120,255,113,113,113,255,108,108,108,255,103,103,103,255, 97, 97, 97,255, + 92, 92, 92,255, 87, 87, 87,255, 82, 82, 82,255, 77, 77, 77,255, 72, 72, 72,255, 66, 66, 66,255, 60, 60, 60,255, 54, 54, 54,255, + 47, 47, 47,255, 39, 39, 39,255, 31, 31, 31,255, 22, 22, 22,255, 12, 12, 12,204, 48, 48, 48,153,106,106,106,255,118,118,118,255, +126,126,126,255,131,131,131,255,134,134,134,255,135,135,135,255,137,137,137,255,138,138,138,255,142,142,142,255,147,147,147,255, +149,149,149,255,148,148,148,255,142,142,142,255,133,133,133,255,124,124,124,255,115,115,115,255,108,108,108,255,102,102,102,255, + 97, 97, 97,255, 92, 92, 92,255, 87, 87, 87,255, 81, 81, 81,255, 75, 75, 75,255, 69, 69, 69,255, 63, 63, 63,255, 57, 57, 57,255, + 49, 49, 49,255, 42, 42, 42,255, 33, 33, 33,255, 24, 24, 24,255, 9, 9, 9,153, 32, 32, 32,102,109,109,109,255,123,123,123,255, +131,131,131,255,136,136,136,255,140,140,140,255,142,142,142,255,144,144,144,255,148,148,148,255,156,156,156,255,168,168,168,255, +176,176,176,255,177,177,177,255,168,168,168,255,153,153,153,255,137,137,137,255,124,124,124,255,114,114,114,255,107,107,107,255, +101,101,101,255, 96, 96, 96,255, 90, 90, 90,255, 85, 85, 85,255, 79, 79, 79,255, 72, 72, 72,255, 66, 66, 66,255, 59, 59, 59,255, + 52, 52, 52,255, 44, 44, 44,255, 35, 35, 35,255, 26, 26, 26,255, 10, 10, 10,153, 17, 17, 17, 51,110,110,110,255,127,127,127,255, +136,136,136,255,142,142,142,255,145,145,145,255,148,148,148,255,151,151,151,255,159,159,159,255,174,174,174,255,195,195,195,255, +212,212,212,255,216,216,216,255,204,204,204,255,179,179,179,255,154,154,154,255,135,135,135,255,121,121,121,255,112,112,112,255, +106,106,106,255, 99, 99, 99,255, 94, 94, 94,255, 88, 88, 88,255, 82, 82, 82,255, 76, 76, 76,255, 69, 69, 69,255, 62, 62, 62,255, + 54, 54, 54,255, 46, 46, 46,255, 37, 37, 37,255, 26, 26, 26,255, 6, 6, 6,102, 0, 0, 0, 0,107,107,107,255,130,130,130,255, +140,140,140,255,146,146,146,255,150,150,150,255,153,153,153,255,158,158,158,255,169,169,169,255,191,191,191,255,219,219,219,255, +246,246,246,255,254,254,254,255,237,237,237,255,204,204,204,255,170,170,170,255,145,145,145,255,127,127,127,255,117,117,117,255, +110,110,110,255,103,103,103,255, 97, 97, 97,255, 91, 91, 91,255, 85, 85, 85,255, 78, 78, 78,255, 71, 71, 71,255, 64, 64, 64,255, + 55, 55, 55,255, 47, 47, 47,255, 37, 37, 37,255, 25, 25, 25,255, 3, 3, 3, 51, 0, 0, 0, 0, 65, 65, 65,153,129,129,129,255, +142,142,142,255,149,149,149,255,154,154,154,255,158,158,158,255,163,163,163,255,176,176,176,255,199,199,199,255,232,232,232,255, +255,255,255,255,255,255,255,255,255,255,255,255,220,220,220,255,181,181,181,255,151,151,151,255,132,132,132,255,121,121,121,255, +113,113,113,255,106,106,106,255,100,100,100,255, 94, 94, 94,255, 87, 87, 87,255, 80, 80, 80,255, 73, 73, 73,255, 65, 65, 65,255, + 57, 57, 57,255, 48, 48, 48,255, 38, 38, 38,255, 16, 16, 16,153, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 51,127,127,127,255, +143,143,143,255,152,152,152,255,157,157,157,255,161,161,161,255,165,165,165,255,177,177,177,255,198,198,198,255,227,227,227,255, +253,253,253,255,255,255,255,255,250,250,250,255,217,217,217,255,181,181,181,255,153,153,153,255,135,135,135,255,124,124,124,255, +117,117,117,255,110,110,110,255,103,103,103,255, 96, 96, 96,255, 89, 89, 89,255, 82, 82, 82,255, 74, 74, 74,255, 66, 66, 66,255, + 57, 57, 57,255, 48, 48, 48,255, 35, 35, 35,255, 10, 10, 10,153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93,204, +141,141,141,255,153,153,153,255,159,159,159,255,163,163,163,255,167,167,167,255,174,174,174,255,188,188,188,255,209,209,209,255, +228,228,228,255,234,234,234,255,224,224,224,255,200,200,200,255,173,173,173,255,151,151,151,255,136,136,136,255,127,127,127,255, +119,119,119,255,112,112,112,255,105,105,105,255, 98, 98, 98,255, 90, 90, 90,255, 83, 83, 83,255, 75, 75, 75,255, 66, 66, 66,255, + 57, 57, 57,255, 46, 46, 46,255, 24, 24, 24,204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 51, +134,134,134,255,151,151,151,255,160,160,160,255,164,164,164,255,167,167,167,255,171,171,171,255,178,178,178,255,189,189,189,255, +200,200,200,255,202,202,202,255,195,195,195,255,180,180,180,255,163,163,163,255,148,148,148,255,137,137,137,255,129,129,129,255, +121,121,121,255,114,114,114,255,107,107,107,255, 99, 99, 99,255, 91, 91, 91,255, 83, 83, 83,255, 74, 74, 74,255, 65, 65, 65,255, + 55, 55, 55,255, 41, 41, 41,255, 7, 7, 7, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49,102,145,145,145,255,157,157,157,255,164,164,164,255,167,167,167,255,170,170,170,255,172,172,172,255,176,176,176,255, +180,180,180,255,179,179,179,255,174,174,174,255,165,165,165,255,155,155,155,255,145,145,145,255,137,137,137,255,130,130,130,255, +122,122,122,255,115,115,115,255,107,107,107,255, 99, 99, 99,255, 91, 91, 91,255, 82, 82, 82,255, 73, 73, 73,255, 63, 63, 63,255, + 50, 50, 50,255, 22, 22, 22,153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 78, 78, 78,153,149,149,149,255,160,160,160,255,166,166,166,255,168,168,168,255,169,169,169,255,170,170,170,255, +169,169,169,255,167,167,167,255,164,164,164,255,158,158,158,255,151,151,151,255,144,144,144,255,137,137,137,255,130,130,130,255, +123,123,123,255,115,115,115,255,106,106,106,255, 98, 98, 98,255, 89, 89, 89,255, 80, 80, 80,255, 70, 70, 70,255, 58, 58, 58,255, + 27, 27, 27,153, 3, 3, 3, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80,153,150,150,150,255,160,160,160,255,165,165,165,255,167,167,167,255,167,167,167,255, +166,166,166,255,163,163,163,255,160,160,160,255,155,155,155,255,149,149,149,255,143,143,143,255,137,137,137,255,129,129,129,255, +121,121,121,255,113,113,113,255,105,105,105,255, 96, 96, 96,255, 86, 86, 86,255, 76, 76, 76,255, 63, 63, 63,255, 38, 38, 38,204, + 7, 7, 7, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 78, 78,153,147,147,147,255,157,157,157,255,161,161,161,255,163,163,163,255, +162,162,162,255,160,160,160,255,157,157,157,255,152,152,152,255,147,147,147,255,141,141,141,255,135,135,135,255,127,127,127,255, +119,119,119,255,110,110,110,255,101,101,101,255, 91, 91, 91,255, 80, 80, 80,255, 66, 66, 66,255, 32, 32, 32,153, 7, 7, 7, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 78, 78, 78,153,147,147,147,255,157,157,157,255,161,161,161,255,163,163,163,255,162,162,162,255,160,160,160,255,157,157,157,255, -152,152,152,255,147,147,147,255,141,141,141,255,135,135,135,255,127,127,127,255,119,119,119,255,110,110,110,255,101,101,101,255, - 91, 91, 91,255, 80, 80, 80,255, 66, 66, 66,255, 32, 32, 32,153, 7, 7, 7, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,134,134,134,255,148,148,148,255,154,154,154,255, +155,155,155,255,154,154,154,255,152,152,152,255,147,147,147,255,142,142,142,255,136,136,136,255,130,130,130,255,122,122,122,255, +114,114,114,255,104,104,104,255, 93, 93, 93,255, 81, 81, 81,255, 54, 54, 54,204, 22, 22, 22,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,134,134,134,255,148,148,148,255,154,154,154,255,155,155,155,255,154,154,154,255,152,152,152,255, -147,147,147,255,142,142,142,255,136,136,136,255,130,130,130,255,122,122,122,255,114,114,114,255,104,104,104,255, 93, 93, 93,255, - 81, 81, 81,255, 54, 54, 54,204, 22, 22, 22,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, 73, 73, 73,153,103,103,103,204, +137,137,137,255,140,140,140,255,140,140,140,255,137,137,137,255,133,133,133,255,127,127,127,255,120,120,120,255,113,113,113,255, +102,102,102,255, 91, 91, 91,255, 64, 64, 64,204, 28, 28, 28,102, 6, 6, 6, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 73, 73,153,103,103,103,204,137,137,137,255,140,140,140,255,140,140,140,255, -137,137,137,255,133,133,133,255,127,127,127,255,120,120,120,255,113,113,113,255,102,102,102,255, 91, 91, 91,255, 64, 64, 64,204, - 28, 28, 28,102, 6, 6, 6, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46,102, 72, 72, 72,153, - 72, 72, 72,153, 92, 92, 92,204, 88, 88, 88,204, 81, 81, 81,204, 54, 54, 54,153, 35, 35, 35,102, 16, 16, 16, 51, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 46, 46,102, 72, 72, 72,153, 72, 72, 72,153, 92, 92, 92,204, 88, 88, 88,204, 81, 81, 81,204, 54, 54, 54,153, + 35, 35, 35,102, 16, 16, 16, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 0, 0,168, 1, 0, 0, 88,110,198, 6, + 0, 0, 0, 0, 33, 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, 84, 69, 84,101,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 0, 0,168, 1, 0, 0,216, 29,218, 3, 0, 0, 0, 0, 33, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,128, 62, 0, 0,160, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 64, 0, 0, 0, 64, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 7, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 8, 0, 0, 0, 1, 0, 1, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,205,204,204, 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, 1, 0, 0, 0, 2, 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, - 84, 69, 84,101,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,112,198, 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, 68, 65, 84, 65, 40, 0, 0, 0, 72,112,198, 6, + 0, 0, 0, 0, 12, 0, 0, 0, 1, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 16, 0, 15, 0,184,112,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 16, 0, 0,184,112,198, 6, + 0, 0, 0, 0, 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, 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,128, 62, 0, 0,160, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 64, 0, 0, 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 8, 0, 0, 0, 1, 0, 1, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -205,204,204, 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, 1, 0, 0, 0, - 2, 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, - 72,121,216, 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, 68, 65, 84, 65, 40, 0, 0, 0, 72,121,216, 3, 0, 0, 0, 0, 12, 0, 0, 0, 1, 0, 0, 0, - 32, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 16, 0, 15, 0, 8, 32,218, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 16, 0, 0, 8, 32,218, 3, 0, 0, 0, 0, 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, @@ -6008,54 +6544,125 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 0, 0,232, 4, 0, 0, 8,129,198, 6, 0, 0, 0, 0, 50, 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, 77, 69, 67,117, 98,101, 0,112,104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,134,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,147,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,143,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,143,198, 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,216,136,198, 6, 0, 0, 0, 0, 24,140,198, 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,136,134,198, 6, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 1, 0, 0, 0, 5, 0, 0, 0, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,137,198, 6, 0, 0, 0, 0,255,255,255,255, +255,255,255,255,255,255,255,255, 0, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255, 1, 0, 0, 0, 5, 0, 0, 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, - 77, 69, 0, 0,232, 4, 0, 0,136, 48,218, 3, 0, 0, 0, 0, 50, 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, 77, 69, 67,117, 98,101, 0,112, -104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 13,217, 3, 0, 0, 0, 0,200,218,208, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 56, 98,198, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 2,211, 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,232,232,217, 3, 0, 0, 0, 0, - 24, 7,163, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,122,209, 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,248, 53,218, 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, 8,145,198, 6, 0, 0, 0, 0,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255, 1, 0, 0, 0, 5, 0, 0, 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,248,140,198, 6, 0, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 1, 0, 0, 0,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 2, 0, 0, 0, 5, 0, 0, 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, 8, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 51, 0, 0, 0,180, 0, 0, 0, 0, 4, 0,128, 63, + 4, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 67, 0, 30, 0, 6, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 8, 0, 0, 0, 56,134,198, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 72, 88,198, 6, 0, 0, 0, 0, 68, 65, 84, 65, 8, 2, 0, 0,136,134,198, 6, 0, 0, 0, 0,124, 1, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,216,136,198, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,216,136,198, 6, 0, 0, 0, 0, 56, 0, 0, 0, + 8, 0, 0, 0, 0, 0,128, 63,255,255,127, 63, 0, 0,128,191,230, 73,230, 73, 26,182, 1, 0, 0, 0,128, 63, 0, 0,128,191, + 0, 0,128,191,230, 73, 26,182, 26,182, 1, 0, 1, 0,128,191,253,255,127,191, 0, 0,128,191, 26,182, 26,182, 26,182, 1, 0, +250,255,127,191, 3, 0,128, 63, 0, 0,128,191, 26,182,230, 73, 26,182, 1, 0, 4, 0,128, 63,247,255,127, 63, 0, 0,128, 63, +230, 73,230, 73,230, 73, 1, 0,245,255,127, 63, 5, 0,128,191, 0, 0,128, 63,230, 73, 26,182,230, 73, 1, 0, 3, 0,128,191, +250,255,127,191, 0, 0,128, 63, 26,182, 26,182,230, 73, 1, 0,255,255,127,191, 0, 0,128, 63, 0, 0,128, 63, 26,182,230, 73, +230, 73, 1, 0, 68, 65, 84, 65, 8, 2, 0, 0,200,137,198, 6, 0, 0, 0, 0,124, 1, 0, 0, 5, 0, 0, 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, 24,140,198, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,144, 0, 0, 0, 24,140,198, 6, 0, 0, 0, 0, 53, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 35, 0, + 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 35, 0, 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 35, 0, 2, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 35, 0, 2, 0, 0, 0, 6, 0, 0, 0, 0, 0, 35, 0, 3, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, 4, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 35, 0, 4, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 35, 0, + 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, 68, 65, 84, 65, 8, 2, 0, 0,248,140,198, 6, 0, 0, 0, 0,124, 1, 0, 0, + 5, 0, 0, 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, 67,111,108, 0, 32, 70, 97, 99,101, 45, 86,101,114,116,101,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 72,143,198, 6, 0, 0, 0, 0, 26, 0, 0, 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, 78, 71,111,110, 32, 70, 97, 99,101, 45, 86,101,114,116,101,120, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,143,198, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 0, 0, 0, 72,143,198, 6, 0, 0, 0, 0, 62, 0, 0, 0, + 24, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255, 1, 0, 0, 0, 5, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,136, 56,218, 3, 0, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0, 0, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 1, 0, 0, 0, 5, 0, 0, 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, 72,156,173, 15, 0, 0, 0, 0, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0, 0,255,255,255,255, 1, 0, 0, 0,255,255,255,255, -255,255,255,255, 2, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255, 3, 0, 0, 0, 5, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 56, 64,218, 3, 0, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0, 0,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 1, 0, 0, 0, 5, 0, 0, 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,168, 61,218, 3, 0, 0, 0, 0, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255, 0, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255, 1, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255, 2, 0, 0, 0, 5, 0, 0, 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, 8, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 51, 0, 0, 0,180, 0, 0, 0, 0, 4, 0,128, 63, 4, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 67, 0, 30, 0, 6, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 8, 0, 0, 0, 24, 13,217, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,152, 7,218, 3, 0, 0, 0, 0, - 68, 65, 84, 65, 8, 2, 0, 0,248, 53,218, 3, 0, 0, 0, 0,124, 1, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +255,255,255,255, 68, 65, 84, 65,192, 0, 0, 0,248,143,198, 6, 0, 0, 0, 0, 59, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, + 9, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 5, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 4, 0, 0, 0, 5, 0, 0, 0, 10, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, + 6, 0, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 9, 0, 0, 0, 68, 65, 84, 65, + 8, 2, 0, 0, 8,145,198, 6, 0, 0, 0, 0,124, 1, 0, 0, 5, 0, 0, 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, 78, 71,111,110, 32, 70, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,147,198, 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,232,232,217, 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, @@ -6067,117 +6674,26 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 72, 0, 0, 0, 88,147,198, 6, 0, 0, 0, 0, 58, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 12, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 2, 0, 16, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 66, 82, 0, 0, + 88, 6, 0, 0,232,147,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 24,158,198, 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, 66, 82, 65,100,100, 0,104, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 8,156,198, 6, 0, 0, 0, 0, 1, 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, - 68, 65, 84, 65,160, 0, 0, 0,232,232,217, 3, 0, 0, 0, 0, 56, 0, 0, 0, 8, 0, 0, 0, 0, 0,128, 63,255,255,127, 63, - 0, 0,128,191,230, 73,230, 73, 26,182, 1, 0, 0, 0,128, 63, 0, 0,128,191, 0, 0,128,191,230, 73, 26,182, 26,182, 1, 0, - 1, 0,128,191,253,255,127,191, 0, 0,128,191, 26,182, 26,182, 26,182, 1, 0,250,255,127,191, 3, 0,128, 63, 0, 0,128,191, - 26,182,230, 73, 26,182, 1, 0, 4, 0,128, 63,247,255,127, 63, 0, 0,128, 63,230, 73,230, 73,230, 73, 1, 0,245,255,127, 63, - 5, 0,128,191, 0, 0,128, 63,230, 73, 26,182,230, 73, 1, 0, 3, 0,128,191,250,255,127,191, 0, 0,128, 63, 26,182, 26,182, -230, 73, 1, 0,255,255,127,191, 0, 0,128, 63, 0, 0,128, 63, 26,182,230, 73,230, 73, 1, 0, 68, 65, 84, 65, 8, 2, 0, 0, -136, 56,218, 3, 0, 0, 0, 0,124, 1, 0, 0, 5, 0, 0, 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, 24, 7,163, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,144, 0, 0, 0, - 24, 7,163, 3, 0, 0, 0, 0, 53, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 35, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 35, 0, - 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 35, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 35, 0, 2, 0, 0, 0, 6, 0, 0, 0, - 0, 0, 35, 0, 3, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 35, 0, 4, 0, 0, 0, - 7, 0, 0, 0, 0, 0, 35, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 35, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, - 68, 65, 84, 65, 8, 2, 0, 0, 72,156,173, 15, 0, 0, 0, 0,124, 1, 0, 0, 5, 0, 0, 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, 72,205,203, 15, 0, 0, 0, 0, - 6, 0, 0, 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, - 67,111,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184,122,209, 15, 0, 0, 0, 0, 9, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,200,136,205, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 8, 2, 0, 0,168, 61,218, 3, 0, 0, 0, 0,124, 1, 0, 0, 5, 0, 0, 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, 67,111,108, 0, 32, 70, 97, 99, -101, 45, 86,101,114,116,101,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 2,211, 3, 0, 0, 0, 0, - 26, 0, 0, 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, - 78, 71,111,110, 32, 70, 97, 99,101, 45, 86,101,114,116,101,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 56, 98,198, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 96, 0, 0, 0,136, 2,211, 3, 0, 0, 0, 0, 62, 0, 0, 0, 24, 0, 0, 0,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 68, 65, 84, 65,192, 0, 0, 0, - 56, 98,198, 3, 0, 0, 0, 0, 59, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, - 2, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 9, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, - 6, 0, 0, 0, 10, 0, 0, 0, 5, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, - 5, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 10, 0, 0, 0, - 6, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, - 7, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 3, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 9, 0, 0, 0, 68, 65, 84, 65, 8, 2, 0, 0, 56, 64,218, 3, 0, 0, 0, 0, -124, 1, 0, 0, 5, 0, 0, 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, 78, 71,111,110, 32, 70, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,200,218,208, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 72, 0, 0, 0,200,218,208, 3, 0, 0, 0, 0, - 58, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, - 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 12, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 16, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 2, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 66, 82, 0, 0, 88, 6, 0, 0,200, 66,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0, 40, 77,218, 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, 66, 82, 65,100,100, 0,104, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 63, 0, 0, 0, 0,104, 75,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6209,49 +6725,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 96, 67,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 12, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,128,148,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,104, 75,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61,248,121,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 8,156,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61,152,157,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,152,157,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 24,158,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,200,166,198, 6, 0, 0, 0, 0,232,147,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 66,108,111, 98, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,248,121,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0,200, 66,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 66,108,111, 98, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,184,164,198, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 13, 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, 63, 0, 0, 0, 0, 8, 84,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6283,52 +6800,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, + 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0,176,158,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0,192, 77,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 8, 84,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,168,122,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,184,164,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186, 72,166,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 72,166,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,200,166,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,120,175,198, 6, 0, 0, 0, 0, 24,158,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 66,108,117,114, 0, 46, 48, 48, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,168,122,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,200, 85,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 40, 77,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 66,108,117,114, 0, 46, 48, 48, 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, 1, 0, 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, 63, + 0, 0, 0, 0,104,173,198, 6, 0, 0, 0, 0, 1, 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, 1, 0, 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, 63, 0, 0, 0, 0,168, 92,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6359,50 +6874,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 96, 86,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 12, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 96,167,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,168, 92,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61, 88,123,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,104,173,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61,248,174,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,248,174,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,120,175,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 40,184,198, 6, 0, 0, 0, 0,200,166,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 66,114,117,115,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 88,123,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,104, 94,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0,200, 85,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 66,114,117,115,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 24,182,198, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 2, 31, 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, 63, 0, 0, 0, 0, 72,101,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6434,51 +6950,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0, 0, 95,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 30, 0, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, + 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0, 16,176,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 72,101,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186, 8,124,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 24,182,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,168,183,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,168,183,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 40,184,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,216,192,198, 6, 0, 0, 0, 0,120,175,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 67,108, 97,121, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 8,124,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0, 8,103,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,168,205,210, 3, 0, 0, 0, 0,104, 94,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 67,108, 97,121, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,200,190,198, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 15, 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, 63, 0, 0, 0, 0,232,109,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6509,49 +7024,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 35, 0, 0, 0, 4, 4, 4, 8, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0,160,103,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, + 4, 4, 4, 8, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, + 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0,192,184,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,232,109,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,184,124,216, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,200,190,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186, 88,192,198, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,184,124,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,168,205,210, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 8,103,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 67,108, 97,121, 32, 83,116,114,105,112,115, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 88,192,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,216,192,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,136,201,198, 6, 0, 0, 0, 0, 40,184,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 67,108, 97,121, 32, 83,116,114,105,112, +115, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,120,199,198, 6, 0, 0, 0, 0, 1, 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, 2, 0, 0, 3, 16, 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, 63, 0, 0, 0, 0, 24,114,219, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6583,52 +7100,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0,160,119, 78, 63, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, + 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0,112,193,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0,160,119, 78, 63, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0, 64,206,210, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 24,114,219, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,152, 62,171, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,120,199,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186, 8,201,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 8,201,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,136,201,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 56,210,198, 6, 0, 0, 0, 0,216,192,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 67,108,111,110,101, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,152, 62,171, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,168,111,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0,168,205,210, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 67,108,111,110,101, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 40,208,198, 6, 0, 0, 0, 0, 1, 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, 1, 0, 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, 63, 0, 0, 0, 0,136,118,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6659,49 +7174,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 51, 51, 51, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 64,112,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 16, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 32,202,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,136,118,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61,104,125,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 40,208,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61,184,209,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,184,209,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 56,210,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,232,218,198, 6, 0, 0, 0, 0,136,201,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 67,114,101, 97,115,101, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,104,125,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0, 72,120,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0,168,111,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 67,114,101, 97,115,101, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,216,216,198, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 18, 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, 63, 0, 0, 0, 0, 40,127,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6733,52 +7250,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 35, 0, 0, 0, + 4, 6, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 62, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, + 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0,208,210,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, 4, 6, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0,224,120,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 40,127,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,228, 97,175,190, 50,131,112, 63,218,243,127,191, 10,183,157,188, 24,126,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,216,216,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,228, 97,175,190, 50,131,112, 63,218,243,127,191, + 10,183,157,188,104,218,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,104,218,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215, 35, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,232,218,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,152,227,198, 6, 0, 0, 0, 0, 56,210,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 68, 97,114,107,101,110, 0, 48, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 24,126,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215, 35, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,232,128,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 72,120,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 68, 97,114,107,101,110, 0, 48, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,136,225,198, 6, 0, 0, 0, 0, 1, 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, 1, 0, 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, 63, 0, 0, 0, 0,200,135,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6809,50 +7324,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0,128,129,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 12, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,128,219,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,200,135,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61,200,126,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,136,225,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61, 24,227,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 24,227,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,152,227,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 72,236,198, 6, 0, 0, 0, 0,232,218,198, 6, + 0, 0, 0, 0, 0, 20, 1,160,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 68,114, 97,119, 0, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,200,126,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,136,137,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0,232,128,218, 3, 0, 0, 0, 0, 0, 20, 1,160,255,255,255,255, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 68,114, 97,119, 0, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 56,234,198, 6, 0, 0, 0, 0, 1, 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, 3, 0, 0, 2, 31, 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, 63, 0, 0, 0, 0, 88,146,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6884,50 +7400,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 35, 0, 0, 0, 0, 4, 0, 8, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0, 32,138,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 30, 0, 35, 0, 0, 0, + 0, 4, 0, 8, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, + 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0, 48,228,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 88,146,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,120,127,216, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 56,234,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,200,235,198, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,120,127,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,104,176,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0,136,137,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 70,105,108,108, 47, 68,101,101,112,101,110, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,200,235,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 72,236,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,248,244,198, 6, 0, 0, 0, 0,152,227,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 70,105,108,108, 47, 68,101,101,112,101, +110, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,232,242,198, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 20, 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, 63, 0, 0, 0, 0, 24,148,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6959,51 +7475,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 20,174,199, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0, 0,177,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 20,174,199, 62, + 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0,224,236,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 24,148,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186, 40,128,216, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,232,242,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,120,244,198, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 40,128,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0, 72,183,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0,104,176,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 70,108, 97,116,116,101,110, 47, 67,111,110,116,114, 97,115,116, 0, 48, 48, 49, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,120,244,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,248,244,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,168,253,198, 6, 0, 0, 0, 0, 72,236,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 70,108, 97,116,116,101,110, 47, 67,111, +110,116,114, 97,115,116, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,152,251,198, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 21, 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, 63, 0, 0, 0, 0,216,149,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7034,50 +7549,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 20,174,199, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0,224,183,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 20,174,199, 62, + 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0,144,245,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,216,149,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,216,128,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,152,251,198, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186, 40,253,198, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 40,253,198, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,168,253,198, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 88, 6,199, 6, 0, 0, 0, 0,248,244,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 71,114, 97, 98, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,216,128,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0, 40,190,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 72,183,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 71,114, 97, 98, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 72, 4,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 22, 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, 63, 0, 0, 0, 0,152,151,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7109,51 +7625,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0,192,190,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 75, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 64,254,198, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,152,151,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,136,129,216, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 72, 4,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,216, 5,199, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,136,129,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0, 8,197,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 40,190,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 73,110,102,108, 97,116,101, 47, 68,101,102,108, 97,116,101, 0, 48, 48, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,216, 5,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 88, 6,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 8, 15,199, 6, 0, 0, 0, 0,168,253,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 73,110,102,108, 97,116,101, 47, 68,101, +102,108, 97,116,101, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,248, 12,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 23, 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, 63, 0, 0, 0, 0, 88,153,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7184,50 +7699,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0, 64, 63, 0, 0, 64, 63, 0, 0, 64, 63, 0, 0,128, 62, 0, 0,128, 62, 0, 0,128, 62, - 68, 65, 84, 65, 56, 1, 0, 0,160,197,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0, 64, 63, 0, 0, 64, 63, 0, 0, 64, 63, + 0, 0,128, 62, 0, 0,128, 62, 0, 0,128, 62, 68, 65, 84, 65, 56, 1, 0, 0,240, 6,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 88,153,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186, 56,130,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,248, 12,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,136, 14,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,136, 14,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 8, 15,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,184, 23,199, 6, 0, 0, 0, 0, 88, 6,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 76, 97,121,101,114, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 56,130,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,232,203,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 8,197,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 76, 97,121,101,114, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,168, 21,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 24, 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, 63, 0, 0, 0, 0, 24,155,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7259,51 +7775,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0,128,204,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,160, 15,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 24,155,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,232,130,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,168, 21,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186, 56, 23,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 56, 23,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,184, 23,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,104, 32,199, 6, 0, 0, 0, 0, 8, 15,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 76,105,103,104,116,101,110, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,232,130,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,200,210,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0,232,203,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 76,105,103,104,116,101,110, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 88, 30,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 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, 63, 0, 0, 0, 0,216,156,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7334,50 +7849,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 96,211,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 12, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 80, 24,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,216,156,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61,152,131,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 88, 30,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61,232, 31,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,232, 31,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,104, 32,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 24, 41,199, 6, 0, 0, 0, 0,184, 23,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 77,105,120, 0,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,152,131,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,168,217,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0,200,210,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 77,105,120, 0,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 8, 39,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 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, 63, 0, 0, 0, 0,152,158,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7409,51 +7925,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 51, 51, 51, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 64,218,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 12, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 0, 33,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,152,158,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61, 72,132,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 8, 39,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61,152, 40,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,152, 40,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 24, 41,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,200, 49,199, 6, 0, 0, 0, 0,104, 32,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 77,117,108,116,105,112,108,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 72,132,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,136,224,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0,168,217,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 77,117,108,116,105,112,108,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,184, 47,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 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, 63, 0, 0, 0, 0, 88,160,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7484,50 +7999,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 32,225,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 12, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,176, 41,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 88,160,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61,248,132,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,184, 47,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61, 72, 49,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 72, 49,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,200, 49,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,120, 58,199, 6, 0, 0, 0, 0, 24, 41,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 78,117,100,103,101, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,248,132,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,184,212,210, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0,136,224,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 78,117,100,103,101, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,104, 56,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 28, 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, 63, 0, 0, 0, 0, 24,162,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7559,51 +8075,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 80,213,210, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 96, 50,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 24,162,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,168,133,216, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,104, 56,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,248, 57,199, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,168,133,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,200,219,210, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0,184,212,210, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 80,105,110, 99,104, 47, 77, 97,103,110,105,102,121, 0, 48, 48, 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,248, 57,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,120, 58,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 40, 67,199, 6, 0, 0, 0, 0,200, 49,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 80,105,110, 99,104, 47, 77, 97,103,110, +105,102,121, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 24, 65,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 29, 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, 63, 0, 0, 0, 0,216,163,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7634,49 +8149,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0, 64, 63, 0, 0, 64, 63, 0, 0, 64, 63, 0, 0,128, 62, 0, 0,128, 62, 0, 0,128, 62, - 68, 65, 84, 65, 56, 1, 0, 0, 96,220,210, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0, 64, 63, 0, 0, 64, 63, 0, 0, 64, 63, + 0, 0,128, 62, 0, 0,128, 62, 0, 0,128, 62, 68, 65, 84, 65, 56, 1, 0, 0, 16, 59,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,216,163,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186, 88,134,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 24, 65,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,168, 66,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,168, 66,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 40, 67,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,216, 75,199, 6, 0, 0, 0, 0,120, 58,199, 6, + 0, 0, 0, 0,253, 21,192, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 80,111,108,105,115,104, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 88,134,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,216,226,210, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0,200,219,210, 3, 0, 0, 0, 0,253, 21,192, 32, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 80,111,108,105,115,104, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,200, 73,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 21, 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, 63, 0, 0, 0, 0,152,165,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7708,51 +8225,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 35, 0, 0, 0, + 4, 4, 4, 1, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 20,174,199, 62, + 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0,192, 67,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, 4, 4, 4, 1, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 20,174,199, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0,112,227,210, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,152,165,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186, 8,135,216, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,200, 73,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186, 88, 75,199, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 8,135,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,232,233,210, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0,216,226,210, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83, 99,114, 97,112,101, 47, 80,101, 97,107,115, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 88, 75,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,216, 75,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,136, 84,199, 6, 0, 0, 0, 0, 40, 67,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83, 99,114, 97,112,101, 47, 80,101, 97, +107,115, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,120, 82,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 30, 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, 63, 0, 0, 0, 0, 88,167,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7784,49 +8300,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 20,174,199, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0,128,234,210, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 20,174,199, 62, + 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0,112, 76,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 88,167,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,184,135,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,120, 82,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186, 8, 84,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 8, 84,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,136, 84,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 56, 93,199, 6, 0, 0, 0, 0,216, 75,199, 6, + 0, 0, 0, 0,168,205,210, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83, 99,117,108,112,116, 68,114, 97,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,184,135,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,248,240,210, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0,232,233,210, 3, 0, 0, 0, 0,168,205,210, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83, 99,117,108,112,116, 68,114, 97,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 40, 91,199, 6, 0, 0, 0, 0, 1, 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, 2, 0, 0, 3, 31, 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, 63, 0, 0, 0, 0, 24,169,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7858,52 +8375,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 35, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0,160,119, 78, 63, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, + 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0, 32, 85,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0,160,119, 78, 63, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0,144,241,210, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 24,169,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,104,136,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 40, 91,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,184, 92,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,184, 92,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 56, 93,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,232,101,199, 6, 0, 0, 0, 0,136, 84,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,109,101, 97,114, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,104,136,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,152,231,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0,248,240,210, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,109,101, 97,114, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,216, 99,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 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, 63, 0, 0, 0, 0,216,170,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7934,50 +8449,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 48,232,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 16, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,208, 93,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,216,170,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61, 24,137,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,216, 99,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61,104,101,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,104,101,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,232,101,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,152,110,199, 6, 0, 0, 0, 0, 56, 93,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,109,111,111,116,104, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 24,137,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,168,238,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0,152,231,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,109,111,111,116,104, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,136,108,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 33, 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, 63, 0, 0, 0, 0,152,172,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8009,50 +8525,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0, 64, 63, 0, 0, 64, 63, 0, 0, 64, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 64,239,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0, 64, 63, 0, 0, 64, 63, 0, 0, 64, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,128,102,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,152,172,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,200,137,216, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,136,108,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186, 24,110,199, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,200,137,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,184,245,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0,168,238,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,110, 97,107,101, 32, 72,111,111,107, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 24,110,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,152,110,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 72,119,199, 6, 0, 0, 0, 0,232,101,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,110, 97,107,101, 32, 72,111,111,107, + 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 56,117,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 34, 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, 63, 0, 0, 0, 0, 88,174,218, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8084,49 +8600,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 80,246,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 75, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 48,111,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 88,174,218, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,120,138,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 56,117,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,200,118,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,200,118,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 72,119,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,248,127,199, 6, 0, 0, 0, 0,152,110,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,111,102,116,101,110, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,120,138,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,200,252,218, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0,184,245,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,111,102,116,101,110, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,232,125,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 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, 63, 0, 0, 0, 0,152,103,219, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8158,52 +8675,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,224,119,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 16, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 96,253,218, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,152,103,219, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61, 40,139,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,232,125,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61,120,127,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,120,127,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,248,127,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0,168,136,199, 6, 0, 0, 0, 0, 72,119,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,117, 98,116,114, 97, 99,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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 40,139,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,216, 3,219, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0,200,252,218, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 83,117, 98,116,114, 97, 99,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, 1, 0, 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, 63, + 0, 0, 0, 0,152,134,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 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, 63, 0, 0, 0, 0, 88,105,219, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8234,49 +8749,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 35, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0,112, 4,219, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 12, 0, 35, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,144,128,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 88,105,219, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, 46,189,194, 61,216,139,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,152,134,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63, 14,215,126,191, 54,189,194, 61, 14,215,126,191, + 46,189,194, 61, 40,136,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 40,136,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, + 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0,168,136,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 88,145,199, 6, 0, 0, 0, 0,248,127,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 84,101,120, 68,114, 97,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,216,139,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62, 31,133,107, 63, 0, 0, 0, 0, 0, 0, 64, 63, 10,215,163, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,232, 10,219, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0,216, 3,219, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 84,101,120, 68,114, 97,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0, 72,143,199, 6, 0, 0, 0, 0, 1, 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, 2, 0, 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, 63, 0, 0, 0, 0, 24,107,219, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8308,52 +8825,50 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 35, 0, 0, 0, + 4, 4, 0, 8, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, 68, 65, 84, 65, 56, 1, 0, 0, 64,137,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 16, 0, 35, 0, 0, 0, 4, 4, 0, 8, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 51, 51, 51, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 20,174,199, 62, 20,174,199, 62, 0, 0,128, 63, - 68, 65, 84, 65, 56, 1, 0, 0,128, 11,219, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0, 24,107,219, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,136,140,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0, 72,143,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,216,144,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,216,144,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 88,145,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 8,154,199, 6, 0, 0, 0, 0,168,136,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 84,104,117,109, 98, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,136,140,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0,248, 17,219, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0, 8, 25,219, 3, 0, 0, 0, 0,232, 10,219, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 84,104,117,109, 98, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,248,151,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 38, 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, 63, 0, 0, 0, 0,216,108,219, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8384,50 +8899,51 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 75, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0,144, 18,219, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 75, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,240,145,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,216,108,219, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186, 56,141,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,248,151,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186,136,153,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,136,153,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, + 88, 6, 0, 0, 8,154,199, 6, 0, 0, 0, 0,123, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,145,199, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 84,119,105,115,116, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 56,141,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 0, 0, 88, 6, 0, 0, 8, 25,219, 3, 0, 0, 0, 0, -123, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 17,219, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 82, 84,119,105,115,116, 0, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 63, + 0, 0, 0, 0,168,160,199, 6, 0, 0, 0, 0, 1, 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, 1, 0, 0, 3, 39, 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, 63, 0, 0, 0, 0,152,110,219, 3, 0, 0, 0, 0, - 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8459,36 +8975,38 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 75, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 10, 0, 0, 0, - 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0,160, 25,219, 3, 0, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, 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, 2, 0, 75, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0,102,102,102, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63,205,204,204, 62, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 62, 0, 0,128, 62, 0, 0,128, 63, 0, 0,128, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,160,154,199, 6, 0, 0, 0, 0, 25, 0, 0, 0, + 1, 0, 0, 0, 1, 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, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 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, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,128, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 64, 1, 0, 0,152,110,219, 3, 0, 0, 0, 0, -119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, - 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191,114, 97,255,186,232,141,216, 3, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, + 64, 1, 0, 0,168,160,199, 6, 0, 0, 0, 0,119, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0,128, 63, 4, 0, 0, 0, 0, 0,128, 67, 0, 0, 0, 0, 0, 0,128, 63,224,255,127,191, 46, 95,255,186,224,255,127,191, +114, 97,255,186, 56,162,199, 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, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0, 56,162,199, 6, + 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, + 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 85, 83, 69, 82, +112, 38, 0, 0, 0,182, 22, 5, 0, 0, 0, 0,209, 0, 0, 0, 1, 0, 0, 0, 1, 8, 17, 1, 63, 6, 0, 0, 5, 0, 0, 0, + 47,116,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 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,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 48, 0, 0, 0,232,141,216, 3, 0, 0, 0, 0,117, 1, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 62,215,163,112, 63, 0, 0, 0, 0, 0, 0, 64, 63,143,194,117, 61, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 85, 83, 69, 82,112, 38, 0, 0, 96, 41,141, 67, 1, 0, 0, 0, -209, 0, 0, 0, 1, 0, 0, 0, 1, 8, 17, 1, 63, 6, 0, 0, 5, 0, 0, 0, 47,116,109,112, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, @@ -8510,10 +9028,9 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 47, 47, 0, 85,115,101,114,115, 47,116,111,110, 47, 68,101,115,107,116,111,112, 47, 0, 45,112,111,119,101,114,112, 99, 47, 98, +105,110, 47, 98,108,101,110,100,101,114, 46, 97,112,112, 47, 67,111,110,116,101,110,116,115, 47, 82,101,115,111,117,114, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 85,115,101,114,115, 47,116,111,110, - 47, 68,101,115,107,116,111,112, 47, 0, 45,112,111,119,101,114,112, 99, 47, 98,105,110, 47, 98,108,101,110,100,101,114, 46, 97, -112,112, 47, 67,111,110,116,101,110,116,115, 47, 82,101,115,111,117,114, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8535,7 +9052,7 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8567,7 +9084,7 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8663,7 +9180,7 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -8751,71 +9268,70 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 35, 0, 0, 0, 2, 0, 94, 1, - 8, 0, 0, 0, 3, 0, 0, 0, 56, 52, 39, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 8, 0, 0, 2, 0, 0, 0, 68,172, 0, 0, - 36, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 72, 0, 0, 0, 0, 0, 64, 0, 5, 0, 2, 0, 88,174,219, 3, 0, 0, 0, 0, - 88,174,219, 3, 0, 0, 0, 0,200,152,170, 3, 0, 0, 0, 0,200,152,170, 3, 0, 0, 0, 0,200,154,199, 3, 0, 0, 0, 0, -200,154,199, 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,184,211,219, 3, 0, 0, 0, 0, 8,219,219, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 35, 0, 0, 0, 2, 0, 94, 1, 8, 0, 0, 0, 3, 0, 0, 0, 56, 52, 39, 0, 0, 0, 0, 0, 1, 0, 2, 0, + 0, 8, 0, 0, 2, 0, 0, 0, 68,172, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 72, 0, 0, 0, 0, 0, 64, 0, + 5, 0, 2, 0,120,201,199, 6, 0, 0, 0, 0,120,201,199, 6, 0, 0, 0, 0,248,176,199, 6, 0, 0, 0, 0,248,176,199, 6, + 0, 0, 0, 0,104,243,199, 6, 0, 0, 0, 0,104,243,199, 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,136,154,198, 6, 0, 0, 0, 0,200,242,199, 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, 32, 0, 0, 0, 1, 0, 2, 0, - 25, 0, 0, 0, 20, 0, 20, 0, 1, 0, 0, 0, 0, 0, 0, 0,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 30, 90,100,191,154,153,153, 62,102,102,102, 63, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 31,250,254, 62, 9, 0, 0, 63,156,153, 25, 63, 0, 0, 0, 0,205,204, 76, 62,205,204, 76, 62, -205,204, 76, 62, 0, 0,128, 63, 44,135, 22, 63, 32,133,235, 62,184,243,125, 62, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -195, 73, 76, 63, 42,135, 86, 63, 0, 0,128, 63, 0, 0, 0, 0, 1, 43,135, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 16, 47, 93, 62, 58,180,200,190, 24, 47, 93,190, 0, 0, 0, 0, 14, 0, 1, 0, 25, 0, 15, 0,120, 0, 60, 0, 3, 0, 5, 0, -128, 0, 0, 0, 0, 0, 0, 0,144, 31, 15, 0, 6, 0, 25, 0, 8, 0, 10, 0,200, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, - 10, 0, 50, 0, 20, 0, 2, 0, 1, 0, 0, 0, 0, 0,128, 63, 60, 0, 0, 0, 0, 0, 2, 0, 2, 0, 8, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, - 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, - 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, - 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, - 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, - 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, - 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, - 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, - 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 32, 0, 0, 0, 1, 0, 2, 0, 25, 0, 0, 0, 20, 0, 20, 0, 1, 0, 0, 0, 0, 0, 0, 0,205,204, 76, 63, +205,204, 76, 63,205,204, 76, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 30, 90,100,191, +154,153,153, 62,102,102,102, 63, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 31,250,254, 62, 9, 0, 0, 63,156,153, 25, 63, + 0, 0, 0, 0,205,204, 76, 62,205,204, 76, 62,205,204, 76, 62, 0, 0,128, 63, 44,135, 22, 63, 32,133,235, 62,184,243,125, 62, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,195, 73, 76, 63, 42,135, 86, 63, 0, 0,128, 63, 0, 0, 0, 0, 1, 43,135, 61, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 16, 47, 93, 62, 58,180,200,190, 24, 47, 93,190, 0, 0, 0, 0, 14, 0, 1, 0, + 25, 0, 15, 0,120, 0, 60, 0, 3, 0, 5, 0,128, 0, 0, 0, 0, 0, 0, 0,144, 31, 15, 0, 6, 0, 25, 0, 8, 0, 10, 0, +200, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 10, 0, 50, 0, 20, 0, 2, 0, 1, 0, 0, 0, 0, 0,128, 63, 60, 0, 0, 0, + 0, 0, 2, 0, 2, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,128, 62, 0, 0, 0, 0, 68, 65, 84, 65,168, 36, 0, 0, - 88,174,219, 3, 0, 0, 0, 0,206, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68,101,102, 97,117,108,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, - 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 1, 0, 15, 0,241,255, 0, 0, - 25, 25, 25,255,153,153,153,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255,255,255,255,255, 1, 0, 0, 0, 25, 0, 0, 0, - 0, 0, 0,255, 70, 70, 70,255, 86,128,194,255,255,255,255,255,255,255,255,255, 0, 0, 0,255, 1, 0, 15, 0,241,255, 0, 0, - 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255, 0, 0, 0,255,255,255,255,255, 1, 0, 15, 0,241,255, 0, 0, - 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 25, 25,255,180,180,180,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255,255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, - 25, 25, 25,255,180,180,180,255,153,153,153,255,128,128,128,255, 0, 0, 0,255,255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, - 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255,255,255,255,255,204,204,204,255, 1, 0, 15, 0,241,255, 0, 0, - 0, 0, 0,255, 63, 63, 63,255, 86,128,194,255,255,255,255,255, 0, 0, 0,255, 0, 0, 0,255, 0, 0, 25, 0,236,255, 0, 0, - 0, 0, 0,255, 25, 25, 25,230, 45, 45, 45,230,100,100,100,255,160,160,160,255,255,255,255,255, 0, 0, 25, 0,236,255, 0, 0, - 0, 0, 0,255, 0, 0, 0, 0, 86,128,194,255,172,172,172,128,255,255,255,255, 0, 0, 0,255, 1, 0, 38, 0, 0, 0, 0, 0, - 0, 0, 0,255, 25, 25, 25,230, 45, 45, 45,230,100,100,100,255,255,255,255,255,255,255,255,255, 0, 0, 25, 0,236,255, 0, 0, - 25, 25, 25,255,128,128,128,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 50, 50,180, 80, 80, 80,180,100,100,100,180,128,128,128,255, 0, 0, 0,255,255,255,255,255, 1, 0, 5, 0,251,255, 0, 0, - 0, 0, 0,255,190,190,190,255,100,100,100,180, 68, 68, 68,255, 0, 0, 0,255,255,255,255,255, 0, 0, 5, 0,251,255, 0, 0, - 0, 0, 0,255, 0, 0, 0, 0, 86,128,194,255, 0, 0, 0,255, 0, 0, 0,255, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, -115,190, 76,255, 90,166, 51,255,240,235,100,255,215,211, 75,255,180, 0,255,255,153, 0,230,255, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 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,128, 62, + 0, 0, 0, 0, 68, 65, 84, 65,168, 36, 0, 0,120,201,199, 6, 0, 0, 0, 0,206, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,101,102, 97,117,108,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, 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255, +255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255, +255,255,255,255, 1, 0, 15, 0,241,255, 0, 0, 25, 25, 25,255,153,153,153,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255, +255,255,255,255, 1, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0,255, 70, 70, 70,255, 86,128,194,255,255,255,255,255,255,255,255,255, + 0, 0, 0,255, 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255, 0, 0, 0,255, +255,255,255,255, 1, 0, 15, 0,241,255, 0, 0, 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255, +255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255,180,180,180,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255, +255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, 25, 25, 25,255,180,180,180,255,153,153,153,255,128,128,128,255, 0, 0, 0,255, +255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255,255,255,255,255, +204,204,204,255, 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0,255, 63, 63, 63,255, 86,128,194,255,255,255,255,255, 0, 0, 0,255, + 0, 0, 0,255, 0, 0, 25, 0,236,255, 0, 0, 0, 0, 0,255, 25, 25, 25,230, 45, 45, 45,230,100,100,100,255,160,160,160,255, +255,255,255,255, 0, 0, 25, 0,236,255, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 86,128,194,255,172,172,172,128,255,255,255,255, + 0, 0, 0,255, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0,255, 25, 25, 25,230, 45, 45, 45,230,100,100,100,255,255,255,255,255, +255,255,255,255, 0, 0, 25, 0,236,255, 0, 0, 25, 25, 25,255,128,128,128,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255, +255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50,180, 80, 80, 80,180,100,100,100,180,128,128,128,255, 0, 0, 0,255, +255,255,255,255, 1, 0, 5, 0,251,255, 0, 0, 0, 0, 0,255,190,190,190,255,100,100,100,180, 68, 68, 68,255, 0, 0, 0,255, +255,255,255,255, 0, 0, 5, 0,251,255, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 86,128,194,255, 0, 0, 0,255, 0, 0, 0,255, + 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0,115,190, 76,255, 90,166, 51,255,240,235,100,255,215,211, 75,255,180, 0,255,255, +153, 0,230,255, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 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, @@ -8823,2397 +9339,2398 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,130,130,130,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 57,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0,255, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,170, 64,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, 32,255,255,255, 75, 75, 75,255,204, 0,153,255, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 32, 0, 0,255, 0, 32, 0,255, 0, 0,128,255, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255,255,255,255,255, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 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,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,200,200,255, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76,255, 0, 0, 0, 0,250,250,250,255, 15, 15, 15,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100,255,140, 25,255,250,250,250,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,130,130,130,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,250,250,250,255, 0, 0, 0, 0,250,250,250,255,250,250,250,255, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 79,101, 73,255,135,177,125,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, -153, 64, 48,255, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255,240,175,144,255, 82, 96,110,255,124,137,150,255, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 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,255,255,255,128, 0, 0, 0,255,255,133, 0,255, 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,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 79,101, 73,255,135,177,125,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 12, 10, 10,128,255,140, 0,255, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 82, 96,110,255,124,137,150,255, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 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,255,255,255,128, 0, 0, 0,255,255,133, 0,255, 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,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 79,101, 73,255,135,177,125,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 12, 10, 10,128,255,140, 0,255, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 82, 96,110,255,124,137,150,255, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 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,255,255,255,128, 0, 0, 0,255,255,133, 0,255, 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,116,116,116,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81,105,135,255, 32, 32,143,255,109, 88,129,255, 78,152, 62,255, 46,143,143,255, -169, 84,124,255,126,126, 80,255,162, 95,111,255,109,145,131,255,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 53, 53,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, -255,255,255, 10,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,114,114,255, 18, 66,176, 38,255,133, 0,178,255,133, 0,127, 0,255, 0,255, -255, 0, 0,255,225,210,195, 35, 0, 0, 0, 0, 0, 0, 0, 0,153,153,153,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -143,143,143,255,198,119,119,255,255, 0, 0,255, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 4, 0,100, 0, 0,255, 0, 0,200,255, -128, 0, 80,255, 95, 95, 0,255, 0,100, 50,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 51,127, 51, 76,130,135,140, 76,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -173,173,173,255,127,112,112,100, 0, 0, 0, 0, 91, 91, 91,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 57,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,255,255,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 4, 5,155,155,155,160,100,104,111,255, -111,106,100,255,104,106,117,255,105,117,110,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100,100,100,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 96,128,255,255,255,255,255,255, 0,170, 0,255,220, 96, 96,255,220, 96, 96,255, 3, 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,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 57,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 94, 94, 94,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0,255, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,170, 64,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, - 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, 32,255,255,255, 75, 75, 75,255,204, 0,153,255, - 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 32, 0, 0,255, 0, 32, 0,255, 0, 0,128,255, 0, 0, 0, 0, 34,221,221,255, - 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255, -219, 37, 18,255,240,255, 64,255,240,144,160,255,255,255,255,255, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, - 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 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,255,255,255,128, 0, 0, 0,255,255,255, 0,255, 4, 0, 0, 0, -255,127,127, 0,255,255,255,255,255,255,255, 0,255,127, 0, 0,255,127,127,127,255,200,200,200,255,255, 0, 0,255, 0, 0,255, -255, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 0, 0,255,189, 17, 17,255,247, 10, 10,255, 0, 0, 0, 0, -247, 64, 24,255,246,105, 19,255,250,153, 0,255, 0, 0, 0, 0, 30,145, 9,255, 89,183, 11,255,131,239, 29,255, 0, 0, 0, 0, - 10, 54,148,255, 54,103,223,255, 94,193,239,255, 0, 0, 0, 0,169, 41, 78,255,193, 65,106,255,240, 93,145,255, 0, 0, 0, 0, - 67, 12,120,255, 84, 58,163,255,135,100,213,255, 0, 0, 0, 0, 36,120, 90,255, 60,149,121,255,111,182,171,255, 0, 0, 0, 0, - 75,112,124,255,106,134,145,255,155,194,205,255, 0, 0, 0, 0,244,201, 12,255,238,194, 54,255,243,255, 0,255, 0, 0, 0, 0, - 30, 32, 36,255, 72, 76, 86,255,255,255,255,255, 0, 0, 0, 0,111, 47,106,255,152, 69,190,255,211, 48,214,255, 0, 0, 0, 0, -108,142, 34,255,127,176, 34,255,187,239, 91,255, 0, 0, 0, 0,141,141,141,255,176,176,176,255,222,222,222,255, 0, 0, 0, 0, -131, 67, 38,255,139, 88, 17,255,189,106, 17,255, 0, 0, 0, 0, 8, 49, 14,255, 28, 67, 11,255, 52, 98, 43,255, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0, -184,211,219, 3, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0,136,212,219, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -105,111, 95,115, 99,101,110,101, 95, 51,100,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 80, 0, 0, 0,136,212,219, 3, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0, 88,213,219, 3, 0, 0, 0, 0, -184,211,219, 3, 0, 0, 0, 0,105,111, 95,115, 99,101,110,101, 95,102, 98,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0, 88,213,219, 3, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0, - 40,214,219, 3, 0, 0, 0, 0,136,212,219, 3, 0, 0, 0, 0,105,111, 95, 97,110,105,109, 95, 98,118,104, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0, 40,214,219, 3, 0, 0, 0, 0, -207, 0, 0, 0, 1, 0, 0, 0,248,214,219, 3, 0, 0, 0, 0, 88,213,219, 3, 0, 0, 0, 0,105,111, 95,109,101,115,104, 95, -112,108,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0, -248,214,219, 3, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0,200,215,219, 3, 0, 0, 0, 0, 40,214,219, 3, 0, 0, 0, 0, -105,111, 95,115, 99,101,110,101, 95,111, 98,106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 80, 0, 0, 0,200,215,219, 3, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0,152,216,219, 3, 0, 0, 0, 0, -248,214,219, 3, 0, 0, 0, 0,105,111, 95,115, 99,101,110,101, 95,120, 51,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0,152,216,219, 3, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0, -104,217,219, 3, 0, 0, 0, 0,200,215,219, 3, 0, 0, 0, 0,105,111, 95,109,101,115,104, 95,115,116,108, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0,104,217,219, 3, 0, 0, 0, 0, -207, 0, 0, 0, 1, 0, 0, 0, 56,218,219, 3, 0, 0, 0, 0,152,216,219, 3, 0, 0, 0, 0,105,111, 95,109,101,115,104, 95, -117,118, 95,108, 97,121,111,117,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, 68, 65, 84, 65, 80, 0, 0, 0, - 56,218,219, 3, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0, 8,219,219, 3, 0, 0, 0, 0,104,217,219, 3, 0, 0, 0, 0, -105,111, 95, 99,117,114,118,101, 95,115,118,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 80, 0, 0, 0, 8,219,219, 3, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 56,218,219, 3, 0, 0, 0, 0, 99,121, 99,108,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,232, 0, 0, 0,200,154,199, 3, 0, 0, 0, 0,199, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,101,102, 97,117,108,116, 32, 83,116,121,108,101, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0,255,255, 0, 0,154,153, 25, 62, 0, 0,128, 63, 0, 0, 12, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0,255,255, 0, 0, 0, 0,128, 62, 0, 0, 0, 0, 0, 0, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0,255,255, 0, 0,154,153, 25, 62, 0, 0,128, 63, 0, 0, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 62, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 8, 0, 5, 0, 5, 0, 8, 0, - 2, 0, 8, 0, 4, 0, 0, 0, 68, 78, 65, 49,136, 4, 1, 0,200,254,218, 15, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 83, 68, 78, 65, 78, 65, 77, 69, 58, 13, 0, 0, 42,110,101,120,116, 0, 42,112,114,101,118, 0, 42,100, 97,116, 97, 0, 42,102, -105,114,115,116, 0, 42,108, 97,115,116, 0,120, 0,121, 0,122, 0,120,109,105,110, 0,120,109, 97,120, 0,121,109,105,110, 0, -121,109, 97,120, 0, 42,112,111,105,110,116,101,114, 0,103,114,111,117,112, 0,118, 97,108, 0,118, 97,108, 50, 0,116,121,112, -101, 0,115,117, 98,116,121,112,101, 0,102,108, 97,103, 0,110, 97,109,101, 91, 54, 52, 93, 0,115, 97,118,101,100, 0,100, 97, -116, 97, 0,108,101,110, 0,116,111,116, 97,108,108,101,110, 0, 42,110,101,119,105,100, 0, 42,108,105, 98, 0,110, 97,109,101, - 91, 54, 54, 93, 0,112, 97,100, 0,117,115, 0,105, 99,111,110, 95,105,100, 0,112, 97,100, 50, 0, 42,112,114,111,112,101,114, -116,105,101,115, 0,105,100, 0, 42,105,100, 98,108,111, 99,107, 0, 42,102,105,108,101,100, 97,116, 97, 0,110, 97,109,101, 91, - 49, 48, 50, 52, 93, 0,102,105,108,101,112, 97,116,104, 91, 49, 48, 50, 52, 93, 0,116,111,116, 0, 42,112, 97,114,101,110,116, - 0,119, 91, 50, 93, 0,104, 91, 50, 93, 0, 99,104, 97,110,103,101,100, 91, 50, 93, 0, 99,104, 97,110,103,101,100, 95,116,105, -109,101,115,116, 97,109,112, 91, 50, 93, 0, 42,114,101, 99,116, 91, 50, 93, 0, 42,111, 98, 0, 98,108,111, 99,107,116,121,112, -101, 0, 97,100,114, 99,111,100,101, 0,110, 97,109,101, 91, 49, 50, 56, 93, 0, 42, 98,112, 0, 42, 98,101,122,116, 0,109, 97, -120,114, 99,116, 0,116,111,116,114, 99,116, 0,118, 97,114,116,121,112,101, 0,116,111,116,118,101,114,116, 0,105,112,111, 0, -101,120,116,114, 97,112, 0,114,116, 0, 98,105,116,109, 97,115,107, 0,115,108,105,100,101, 95,109,105,110, 0,115,108,105,100, -101, 95,109, 97,120, 0, 99,117,114,118, 97,108, 0, 42,100,114,105,118,101,114, 0, 99,117,114,118,101, 0, 99,117,114, 0,115, -104,111,119,107,101,121, 0,109,117,116,101,105,112,111, 0,112,111,115, 0,114,101,108, 97,116,105,118,101, 0,116,111,116,101, -108,101,109, 0, 42,119,101,105,103,104,116,115, 0,118,103,114,111,117,112, 91, 54, 52, 93, 0,115,108,105,100,101,114,109,105, -110, 0,115,108,105,100,101,114,109, 97,120, 0,117,105,100, 0,112, 97,100, 51, 0, 42, 97,100,116, 0, 42,114,101,102,107,101, -121, 0,101,108,101,109,115,116,114, 91, 54, 52, 93, 0,101,108,101,109,115,105,122,101, 0, 98,108,111, 99,107, 0, 42,105,112, -111, 0, 42,102,114,111,109, 0,116,111,116,107,101,121, 0,115,108,117,114,112,104, 0,117,105,100,103,101,110, 0, 42,108,105, -110,101, 0, 42,102,111,114,109, 97,116, 0, 98,108,101,110, 0,108,105,110,101,110,111, 0,115,116, 97,114,116, 0,101,110,100, - 0,112, 97,100, 49, 0,102,108, 97,103,115, 0, 99,111,108,111,114, 91, 52, 93, 0,112, 97,100, 91, 52, 93, 0, 42,110, 97,109, -101, 0,110,108,105,110,101,115, 0,108,105,110,101,115, 0, 42, 99,117,114,108, 0, 42,115,101,108,108, 0, 99,117,114, 99, 0, -115,101,108, 99, 0,109, 97,114,107,101,114,115, 0, 42,117,110,100,111, 95, 98,117,102, 0,117,110,100,111, 95,112,111,115, 0, -117,110,100,111, 95,108,101,110, 0, 42, 99,111,109,112,105,108,101,100, 0,109,116,105,109,101, 0,115,105,122,101, 0,115,101, -101,107, 0,100,116,120, 0,112, 97,115,115,101,112, 97,114,116, 97,108,112,104, 97, 0, 99,108,105,112,115,116, 97, 0, 99,108, -105,112,101,110,100, 0,108,101,110,115, 0,111,114,116,104,111, 95,115, 99, 97,108,101, 0,100,114, 97,119,115,105,122,101, 0, -115,101,110,115,111,114, 95,120, 0,115,101,110,115,111,114, 95,121, 0,115,104,105,102,116,120, 0,115,104,105,102,116,121, 0, - 89, 70, 95,100,111,102,100,105,115,116, 0, 42,100,111,102, 95,111, 98, 0,115,101,110,115,111,114, 95,102,105,116, 0,112, 97, -100, 91, 55, 93, 0, 42,115, 99,101,110,101, 0,102,114, 97,109,101,110,114, 0,102,114, 97,109,101,115, 0,111,102,102,115,101, -116, 0,115,102,114, 97, 0,102,105,101, 95,105,109, 97, 0, 99,121, 99,108, 0,111,107, 0,109,117,108,116,105, 95,105,110,100, -101,120, 0,108, 97,121,101,114, 0,112, 97,115,115, 0,105, 98,117,102,115, 0, 42,103,112,117,116,101,120,116,117,114,101, 0, - 42, 97,110,105,109, 0, 42,114,114, 0, 42,114,101,110,100,101,114,115, 91, 56, 93, 0,114,101,110,100,101,114, 95,115,108,111, -116, 0,108, 97,115,116, 95,114,101,110,100,101,114, 95,115,108,111,116, 0,115,111,117,114, 99,101, 0,108, 97,115,116,102,114, - 97,109,101, 0,116,112, 97,103,101,102,108, 97,103, 0,116,111,116, 98,105,110,100, 0,120,114,101,112, 0,121,114,101,112, 0, -116,119,115,116, 97, 0,116,119,101,110,100, 0, 98,105,110,100, 99,111,100,101, 0, 42,114,101,112, 98,105,110,100, 0, 42,112, - 97, 99,107,101,100,102,105,108,101, 0, 42,112,114,101,118,105,101,119, 0,108, 97,115,116,117,112,100, 97,116,101, 0,108, 97, -115,116,117,115,101,100, 0, 97,110,105,109,115,112,101,101,100, 0,103,101,110, 95,120, 0,103,101,110, 95,121, 0,103,101,110, - 95,116,121,112,101, 0,103,101,110, 95,102,108, 97,103, 0, 97,115,112,120, 0, 97,115,112,121, 0,116,101,120, 99,111, 0,109, - 97,112,116,111, 0,109, 97,112,116,111,110,101,103, 0, 98,108,101,110,100,116,121,112,101, 0, 42,111, 98,106,101, 99,116, 0, - 42,116,101,120, 0,117,118,110, 97,109,101, 91, 54, 52, 93, 0,112,114,111,106,120, 0,112,114,111,106,121, 0,112,114,111,106, -122, 0,109, 97,112,112,105,110,103, 0,111,102,115, 91, 51, 93, 0,115,105,122,101, 91, 51, 93, 0,114,111,116, 0,116,101,120, -102,108, 97,103, 0, 99,111,108,111,114,109,111,100,101,108, 0,112,109, 97,112,116,111, 0,112,109, 97,112,116,111,110,101,103, - 0,110,111,114,109, 97,112,115,112, 97, 99,101, 0,119,104,105, 99,104, 95,111,117,116,112,117,116, 0, 98,114,117,115,104, 95, -109, 97,112, 95,109,111,100,101, 0,114, 0,103, 0, 98, 0,107, 0,100,101,102, 95,118, 97,114, 0, 99,111,108,102, 97, 99, 0, -118, 97,114,102, 97, 99, 0,110,111,114,102, 97, 99, 0,100,105,115,112,102, 97, 99, 0,119, 97,114,112,102, 97, 99, 0, 99,111, -108,115,112,101, 99,102, 97, 99, 0,109,105,114,114,102, 97, 99, 0, 97,108,112,104, 97,102, 97, 99, 0,100,105,102,102,102, 97, - 99, 0,115,112,101, 99,102, 97, 99, 0,101,109,105,116,102, 97, 99, 0,104, 97,114,100,102, 97, 99, 0,114, 97,121,109,105,114, -114,102, 97, 99, 0,116,114, 97,110,115,108,102, 97, 99, 0, 97,109, 98,102, 97, 99, 0, 99,111,108,101,109,105,116,102, 97, 99, - 0, 99,111,108,114,101,102,108,102, 97, 99, 0, 99,111,108,116,114, 97,110,115,102, 97, 99, 0,100,101,110,115,102, 97, 99, 0, -115, 99, 97,116,116,101,114,102, 97, 99, 0,114,101,102,108,102, 97, 99, 0,116,105,109,101,102, 97, 99, 0,108,101,110,103,116, -104,102, 97, 99, 0, 99,108,117,109,112,102, 97, 99, 0,100, 97,109,112,102, 97, 99, 0,107,105,110,107,102, 97, 99, 0,114,111, -117,103,104,102, 97, 99, 0,112, 97,100,101,110,115,102, 97, 99, 0,103,114, 97,118,105,116,121,102, 97, 99, 0,108,105,102,101, -102, 97, 99, 0,115,105,122,101,102, 97, 99, 0,105,118,101,108,102, 97, 99, 0,102,105,101,108,100,102, 97, 99, 0,115,104, 97, -100,111,119,102, 97, 99, 0,122,101,110,117,112,102, 97, 99, 0,122,101,110,100,111,119,110,102, 97, 99, 0, 98,108,101,110,100, -102, 97, 99, 0, 42,104, 97,110,100,108,101, 0, 42,112,110, 97,109,101, 0, 42,115,116,110, 97,109,101,115, 0,115,116,121,112, -101,115, 0,118, 97,114,115, 0, 42,118, 97,114,115,116,114, 0, 42,114,101,115,117,108,116, 0, 42, 99,102,114, 97, 0,100, 97, -116, 97, 91, 51, 50, 93, 0, 40, 42,100,111,105,116, 41, 40, 41, 0, 40, 42,105,110,115,116, 97,110, 99,101, 95,105,110,105,116, - 41, 40, 41, 0, 40, 42, 99, 97,108,108, 98, 97, 99,107, 41, 40, 41, 0,118,101,114,115,105,111,110, 0, 97, 0,105,112,111,116, -121,112,101, 0, 42,105,109, 97, 0, 42, 99,117, 98,101, 91, 54, 93, 0,105,109, 97,116, 91, 52, 93, 91, 52, 93, 0,111, 98,105, -109, 97,116, 91, 51, 93, 91, 51, 93, 0,115,116,121,112,101, 0,118,105,101,119,115, 99, 97,108,101, 0,110,111,116,108, 97,121, - 0, 99,117, 98,101,114,101,115, 0,100,101,112,116,104, 0,114,101, 99, 97,108, 99, 0,108, 97,115,116,115,105,122,101, 0,102, - 97,108,108,111,102,102, 95,116,121,112,101, 0,102, 97,108,108,111,102,102, 95,115,111,102,116,110,101,115,115, 0,114, 97,100, -105,117,115, 0, 99,111,108,111,114, 95,115,111,117,114, 99,101, 0,116,111,116,112,111,105,110,116,115, 0,112,100,112, 97,100, - 0,112,115,121,115, 0,112,115,121,115, 95, 99, 97, 99,104,101, 95,115,112, 97, 99,101, 0,111, 98, 95, 99, 97, 99,104,101, 95, -115,112, 97, 99,101, 0, 42,112,111,105,110,116, 95,116,114,101,101, 0, 42,112,111,105,110,116, 95,100, 97,116, 97, 0,110,111, -105,115,101, 95,115,105,122,101, 0,110,111,105,115,101, 95,100,101,112,116,104, 0,110,111,105,115,101, 95,105,110,102,108,117, -101,110, 99,101, 0,110,111,105,115,101, 95, 98, 97,115,105,115, 0,112,100,112, 97,100, 51, 91, 51, 93, 0,110,111,105,115,101, - 95,102, 97, 99, 0,115,112,101,101,100, 95,115, 99, 97,108,101, 0,102, 97,108,108,111,102,102, 95,115,112,101,101,100, 95,115, - 99, 97,108,101, 0,112,100,112, 97,100, 50, 0, 42, 99,111, 98, 97, 0, 42,102, 97,108,108,111,102,102, 95, 99,117,114,118,101, - 0,114,101,115,111,108, 91, 51, 93, 0,105,110,116,101,114,112, 95,116,121,112,101, 0,102,105,108,101, 95,102,111,114,109, 97, -116, 0,101,120,116,101,110,100, 0,115,109,111,107,101,100, 95,116,121,112,101, 0,105,110,116, 95,109,117,108,116,105,112,108, -105,101,114, 0,115,116,105,108,108, 95,102,114, 97,109,101, 0,115,111,117,114, 99,101, 95,112, 97,116,104, 91, 49, 48, 50, 52, - 93, 0, 42,100, 97,116, 97,115,101,116, 0, 99, 97, 99,104,101,100,102,114, 97,109,101, 0,111, 99,101, 97,110,109,111,100, 91, - 54, 52, 93, 0,111,117,116,112,117,116, 0,110,111,105,115,101,115,105,122,101, 0,116,117,114, 98,117,108, 0, 98,114,105,103, -104,116, 0, 99,111,110,116,114, 97,115,116, 0,115, 97,116,117,114, 97,116,105,111,110, 0,114,102, 97, 99, 0,103,102, 97, 99, - 0, 98,102, 97, 99, 0,102,105,108,116,101,114,115,105,122,101, 0,109,103, 95, 72, 0,109,103, 95,108, 97, 99,117,110, 97,114, -105,116,121, 0,109,103, 95,111, 99,116, 97,118,101,115, 0,109,103, 95,111,102,102,115,101,116, 0,109,103, 95,103, 97,105,110, - 0,100,105,115,116, 95, 97,109,111,117,110,116, 0,110,115, 95,111,117,116,115, 99, 97,108,101, 0,118,110, 95,119, 49, 0,118, -110, 95,119, 50, 0,118,110, 95,119, 51, 0,118,110, 95,119, 52, 0,118,110, 95,109,101,120,112, 0,118,110, 95,100,105,115,116, -109, 0,118,110, 95, 99,111,108,116,121,112,101, 0,110,111,105,115,101,100,101,112,116,104, 0,110,111,105,115,101,116,121,112, -101, 0,110,111,105,115,101, 98, 97,115,105,115, 0,110,111,105,115,101, 98, 97,115,105,115, 50, 0,105,109, 97,102,108, 97,103, - 0, 99,114,111,112,120,109,105,110, 0, 99,114,111,112,121,109,105,110, 0, 99,114,111,112,120,109, 97,120, 0, 99,114,111,112, -121,109, 97,120, 0,116,101,120,102,105,108,116,101,114, 0, 97,102,109, 97,120, 0,120,114,101,112,101, 97,116, 0,121,114,101, -112,101, 97,116, 0, 99,104,101, 99,107,101,114,100,105,115,116, 0,110, 97, 98,108, 97, 0,105,117,115,101,114, 0, 42,110,111, -100,101,116,114,101,101, 0, 42,112,108,117,103,105,110, 0, 42,101,110,118, 0, 42,112,100, 0, 42,118,100, 0, 42,111,116, 0, -117,115,101, 95,110,111,100,101,115, 0,108,111, 99, 91, 51, 93, 0,114,111,116, 91, 51, 93, 0,109, 97,116, 91, 52, 93, 91, 52, - 93, 0,109,105,110, 91, 51, 93, 0,109, 97,120, 91, 51, 93, 0, 99,111, 98, 97, 0, 98,108,101,110,100, 95, 99,111,108,111,114, - 91, 51, 93, 0, 98,108,101,110,100, 95,102, 97, 99,116,111,114, 0, 98,108,101,110,100, 95,116,121,112,101, 0,112, 97,100, 91, - 51, 93, 0,109,111,100,101, 0,116,111,116,101,120, 0,115,104,100,119,114, 0,115,104,100,119,103, 0,115,104,100,119, 98, 0, -115,104,100,119,112, 97,100, 0,101,110,101,114,103,121, 0,100,105,115,116, 0,115,112,111,116,115,105,122,101, 0,115,112,111, -116, 98,108,101,110,100, 0,104, 97,105,110,116, 0, 97,116,116, 49, 0, 97,116,116, 50, 0, 42, 99,117,114,102, 97,108,108,111, -102,102, 0,115,104, 97,100,115,112,111,116,115,105,122,101, 0, 98,105, 97,115, 0,115,111,102,116, 0, 99,111,109,112,114,101, -115,115,116,104,114,101,115,104, 0,112, 97,100, 53, 91, 51, 93, 0, 98,117,102,115,105,122,101, 0,115, 97,109,112, 0, 98,117, -102,102,101,114,115, 0,102,105,108,116,101,114,116,121,112,101, 0, 98,117,102,102,108, 97,103, 0, 98,117,102,116,121,112,101, - 0,114, 97,121, 95,115, 97,109,112, 0,114, 97,121, 95,115, 97,109,112,121, 0,114, 97,121, 95,115, 97,109,112,122, 0,114, 97, -121, 95,115, 97,109,112, 95,116,121,112,101, 0, 97,114,101, 97, 95,115,104, 97,112,101, 0, 97,114,101, 97, 95,115,105,122,101, - 0, 97,114,101, 97, 95,115,105,122,101,121, 0, 97,114,101, 97, 95,115,105,122,101,122, 0, 97,100, 97,112,116, 95,116,104,114, -101,115,104, 0,114, 97,121, 95,115, 97,109,112, 95,109,101,116,104,111,100, 0,116,101,120, 97, 99,116, 0,115,104, 97,100,104, - 97,108,111,115,116,101,112, 0,115,117,110, 95,101,102,102,101, 99,116, 95,116,121,112,101, 0,115,107,121, 98,108,101,110,100, -116,121,112,101, 0,104,111,114,105,122,111,110, 95, 98,114,105,103,104,116,110,101,115,115, 0,115,112,114,101, 97,100, 0,115, -117,110, 95, 98,114,105,103,104,116,110,101,115,115, 0,115,117,110, 95,115,105,122,101, 0, 98, 97, 99,107,115, 99, 97,116,116, -101,114,101,100, 95,108,105,103,104,116, 0,115,117,110, 95,105,110,116,101,110,115,105,116,121, 0, 97,116,109, 95,116,117,114, - 98,105,100,105,116,121, 0, 97,116,109, 95,105,110,115, 99, 97,116,116,101,114,105,110,103, 95,102, 97, 99,116,111,114, 0, 97, -116,109, 95,101,120,116,105,110, 99,116,105,111,110, 95,102, 97, 99,116,111,114, 0, 97,116,109, 95,100,105,115,116, 97,110, 99, -101, 95,102, 97, 99,116,111,114, 0,115,107,121, 98,108,101,110,100,102, 97, 99, 0,115,107,121, 95,101,120,112,111,115,117,114, -101, 0,115,107,121, 95, 99,111,108,111,114,115,112, 97, 99,101, 0,112, 97,100, 52, 91, 54, 93, 0, 42,109,116,101,120, 91, 49, - 56, 93, 0,112,114, 95,116,101,120,116,117,114,101, 0,112, 97,100, 54, 91, 52, 93, 0,100,101,110,115,105,116,121, 0,101,109, -105,115,115,105,111,110, 0,115, 99, 97,116,116,101,114,105,110,103, 0,114,101,102,108,101, 99,116,105,111,110, 0,101,109,105, -115,115,105,111,110, 95, 99,111,108, 91, 51, 93, 0,116,114, 97,110,115,109,105,115,115,105,111,110, 95, 99,111,108, 91, 51, 93, - 0,114,101,102,108,101, 99,116,105,111,110, 95, 99,111,108, 91, 51, 93, 0,100,101,110,115,105,116,121, 95,115, 99, 97,108,101, - 0,100,101,112,116,104, 95, 99,117,116,111,102,102, 0, 97,115,121,109,109,101,116,114,121, 0,115,116,101,112,115,105,122,101, - 95,116,121,112,101, 0,115,104, 97,100,101,102,108, 97,103, 0,115,104, 97,100,101, 95,116,121,112,101, 0,112,114,101, 99, 97, - 99,104,101, 95,114,101,115,111,108,117,116,105,111,110, 0,115,116,101,112,115,105,122,101, 0,109,115, 95,100,105,102,102, 0, -109,115, 95,105,110,116,101,110,115,105,116,121, 0,109,115, 95,115,112,114,101, 97,100, 0, 97,108,112,104, 97, 95, 98,108,101, -110,100, 0,102, 97, 99,101, 95,111,114,105,101,110,116, 97,116,105,111,110, 0,109, 97,116,101,114,105, 97,108, 95,116,121,112, -101, 0,115,112,101, 99,114, 0,115,112,101, 99,103, 0,115,112,101, 99, 98, 0,109,105,114,114, 0,109,105,114,103, 0,109,105, -114, 98, 0, 97,109, 98,114, 0, 97,109, 98, 98, 0, 97,109, 98,103, 0, 97,109, 98, 0,101,109,105,116, 0, 97,110,103, 0,115, -112,101, 99,116,114, 97, 0,114, 97,121, 95,109,105,114,114,111,114, 0, 97,108,112,104, 97, 0,114,101,102, 0,115,112,101, 99, - 0,122,111,102,102,115, 0, 97,100,100, 0,116,114, 97,110,115,108,117, 99,101,110, 99,121, 0,118,111,108, 0,103, 97,109,101, - 0,102,114,101,115,110,101,108, 95,109,105,114, 0,102,114,101,115,110,101,108, 95,109,105,114, 95,105, 0,102,114,101,115,110, -101,108, 95,116,114, 97, 0,102,114,101,115,110,101,108, 95,116,114, 97, 95,105, 0,102,105,108,116,101,114, 0,116,120, 95,108, -105,109,105,116, 0,116,120, 95,102, 97,108,108,111,102,102, 0,114, 97,121, 95,100,101,112,116,104, 0,114, 97,121, 95,100,101, -112,116,104, 95,116,114, 97, 0,104, 97,114, 0,115,101,101,100, 49, 0,115,101,101,100, 50, 0,103,108,111,115,115, 95,109,105, -114, 0,103,108,111,115,115, 95,116,114, 97, 0,115, 97,109,112, 95,103,108,111,115,115, 95,109,105,114, 0,115, 97,109,112, 95, -103,108,111,115,115, 95,116,114, 97, 0, 97,100, 97,112,116, 95,116,104,114,101,115,104, 95,109,105,114, 0, 97,100, 97,112,116, - 95,116,104,114,101,115,104, 95,116,114, 97, 0, 97,110,105,115,111, 95,103,108,111,115,115, 95,109,105,114, 0,100,105,115,116, - 95,109,105,114, 0,102, 97,100,101,116,111, 95,109,105,114, 0,115,104, 97,100,101, 95,102,108, 97,103, 0,109,111,100,101, 95, -108, 0,102,108, 97,114,101, 99, 0,115,116, 97,114, 99, 0,108,105,110,101, 99, 0,114,105,110,103, 99, 0,104, 97,115,105,122, -101, 0,102,108, 97,114,101,115,105,122,101, 0,115,117, 98,115,105,122,101, 0,102,108, 97,114,101, 98,111,111,115,116, 0,115, -116,114, 97,110,100, 95,115,116, 97, 0,115,116,114, 97,110,100, 95,101,110,100, 0,115,116,114, 97,110,100, 95,101, 97,115,101, - 0,115,116,114, 97,110,100, 95,115,117,114,102,110,111,114, 0,115,116,114, 97,110,100, 95,109,105,110, 0,115,116,114, 97,110, -100, 95,119,105,100,116,104,102, 97,100,101, 0,115,116,114, 97,110,100, 95,117,118,110, 97,109,101, 91, 54, 52, 93, 0,115, 98, -105, 97,115, 0,108, 98,105, 97,115, 0,115,104, 97,100, 95, 97,108,112,104, 97, 0,115,101,112,116,101,120, 0,114,103, 98,115, -101,108, 0,112,114, 95,116,121,112,101, 0,112,114, 95, 98, 97, 99,107, 0,112,114, 95,108, 97,109,112, 0,109,108, 95,102,108, - 97,103, 0,100,105,102,102, 95,115,104, 97,100,101,114, 0,115,112,101, 99, 95,115,104, 97,100,101,114, 0,114,111,117,103,104, -110,101,115,115, 0,114,101,102,114, 97, 99, 0,112, 97,114, 97,109, 91, 52, 93, 0,114,109,115, 0,100, 97,114,107,110,101,115, -115, 0, 42,114, 97,109,112, 95, 99,111,108, 0, 42,114, 97,109,112, 95,115,112,101, 99, 0,114, 97,109,112,105,110, 95, 99,111, -108, 0,114, 97,109,112,105,110, 95,115,112,101, 99, 0,114, 97,109,112, 98,108,101,110,100, 95, 99,111,108, 0,114, 97,109,112, - 98,108,101,110,100, 95,115,112,101, 99, 0,114, 97,109,112, 95,115,104,111,119, 0,114, 97,109,112,102, 97, 99, 95, 99,111,108, - 0,114, 97,109,112,102, 97, 99, 95,115,112,101, 99, 0, 42,103,114,111,117,112, 0,102,114,105, 99,116,105,111,110, 0,102,104, - 0,114,101,102,108,101, 99,116, 0,102,104,100,105,115,116, 0,120,121,102,114,105, 99,116, 0,100,121,110, 97,109,111,100,101, - 0,115,115,115, 95,114, 97,100,105,117,115, 91, 51, 93, 0,115,115,115, 95, 99,111,108, 91, 51, 93, 0,115,115,115, 95,101,114, -114,111,114, 0,115,115,115, 95,115, 99, 97,108,101, 0,115,115,115, 95,105,111,114, 0,115,115,115, 95, 99,111,108,102, 97, 99, - 0,115,115,115, 95,116,101,120,102, 97, 99, 0,115,115,115, 95,102,114,111,110,116, 0,115,115,115, 95, 98, 97, 99,107, 0,115, -115,115, 95,102,108, 97,103, 0,115,115,115, 95,112,114,101,115,101,116, 0,109, 97,112,116,111, 95,116,101,120,116,117,114,101, -100, 0,115,104, 97,100,111,119,111,110,108,121, 95,102,108, 97,103, 0,105,110,100,101,120, 0,103,112,117,109, 97,116,101,114, -105, 97,108, 0, 42, 98, 98, 0,115,101,108, 99,111,108, 49, 0,115,101,108, 99,111,108, 50, 0,113,117, 97,116, 91, 52, 93, 0, -101,120,112,120, 0,101,120,112,121, 0,101,120,112,122, 0,114, 97,100, 0,114, 97,100, 50, 0,115, 0, 42,109, 97,116, 0, 42, -105,109, 97,116, 0,101,108,101,109,115, 0,100,105,115,112, 0, 42,101,100,105,116,101,108,101,109,115, 0, 42, 42,109, 97,116, - 0,102,108, 97,103, 50, 0,116,111,116, 99,111,108, 0,119,105,114,101,115,105,122,101, 0,114,101,110,100,101,114,115,105,122, -101, 0,116,104,114,101,115,104, 0, 42,108, 97,115,116,101,108,101,109, 0,118,101, 99, 91, 51, 93, 91, 51, 93, 0, 97,108,102, - 97, 0,119,101,105,103,104,116, 0,104, 49, 0,104, 50, 0,102, 49, 0,102, 50, 0,102, 51, 0,104,105,100,101, 0,118,101, 99, - 91, 52, 93, 0,109, 97,116, 95,110,114, 0,112,110,116,115,117, 0,112,110,116,115,118, 0,114,101,115,111,108,117, 0,114,101, -115,111,108,118, 0,111,114,100,101,114,117, 0,111,114,100,101,114,118, 0,102,108, 97,103,117, 0,102,108, 97,103,118, 0, 42, -107,110,111,116,115,117, 0, 42,107,110,111,116,115,118, 0,116,105,108,116, 95,105,110,116,101,114,112, 0,114, 97,100,105,117, -115, 95,105,110,116,101,114,112, 0, 99,104, 97,114,105,100,120, 0,107,101,114,110, 0,119, 0,104, 0,110,117,114, 98,115, 0, - 42,107,101,121,105,110,100,101,120, 0,115,104, 97,112,101,110,114, 0,110,117,114, 98, 0, 42,101,100,105,116,110,117,114, 98, - 0, 42, 98,101,118,111, 98,106, 0, 42,116, 97,112,101,114,111, 98,106, 0, 42,116,101,120,116,111,110, 99,117,114,118,101, 0, - 42,112, 97,116,104, 0, 42,107,101,121, 0, 98,101,118, 0,100,114, 97,119,102,108, 97,103, 0,116,119,105,115,116, 95,109,111, -100,101, 0,116,119,105,115,116, 95,115,109,111,111,116,104, 0,115,109, 97,108,108, 99, 97,112,115, 95,115, 99, 97,108,101, 0, -112, 97,116,104,108,101,110, 0, 98,101,118,114,101,115,111,108, 0,119,105,100,116,104, 0,101,120,116, 49, 0,101,120,116, 50, - 0,114,101,115,111,108,117, 95,114,101,110, 0,114,101,115,111,108,118, 95,114,101,110, 0, 97, 99,116,110,117, 0, 42,108, 97, -115,116,115,101,108, 0,115,112, 97, 99,101,109,111,100,101, 0,115,112, 97, 99,105,110,103, 0,108,105,110,101,100,105,115,116, - 0,115,104,101, 97,114, 0,102,115,105,122,101, 0,119,111,114,100,115,112, 97, 99,101, 0,117,108,112,111,115, 0,117,108,104, -101,105,103,104,116, 0,120,111,102, 0,121,111,102, 0,108,105,110,101,119,105,100,116,104, 0, 42,115,116,114, 0, 42,115,101, -108, 98,111,120,101,115, 0, 42,101,100,105,116,102,111,110,116, 0,102, 97,109,105,108,121, 91, 50, 52, 93, 0, 42,118,102,111, -110,116, 0, 42,118,102,111,110,116, 98, 0, 42,118,102,111,110,116,105, 0, 42,118,102,111,110,116, 98,105, 0,115,101,112, 99, -104, 97,114, 0, 99,116,105,109,101, 0,116,111,116, 98,111,120, 0, 97, 99,116, 98,111,120, 0, 42,116, 98, 0,115,101,108,115, -116, 97,114,116, 0,115,101,108,101,110,100, 0, 42,115,116,114,105,110,102,111, 0, 99,117,114,105,110,102,111, 0, 42,109,112, -111,108,121, 0, 42,109,116,112,111,108,121, 0, 42,109,108,111,111,112, 0, 42,109,108,111,111,112,117,118, 0, 42,109,108,111, -111,112, 99,111,108, 0, 42,109,102, 97, 99,101, 0, 42,109,116,102, 97, 99,101, 0, 42,116,102, 97, 99,101, 0, 42,109,118,101, -114,116, 0, 42,109,101,100,103,101, 0, 42,100,118,101,114,116, 0, 42,109, 99,111,108, 0, 42,109,115,116,105, 99,107,121, 0, - 42,116,101,120, 99,111,109,101,115,104, 0, 42,109,115,101,108,101, 99,116, 0, 42,101,100,105,116, 95, 98,116,109,101,115,104, - 0,118,100, 97,116, 97, 0,101,100, 97,116, 97, 0,102,100, 97,116, 97, 0,112,100, 97,116, 97, 0,108,100, 97,116, 97, 0,116, -111,116,101,100,103,101, 0,116,111,116,102, 97, 99,101, 0,116,111,116,115,101,108,101, 99,116, 0,116,111,116,112,111,108,121, - 0,116,111,116,108,111,111,112, 0, 97, 99,116, 95,102, 97, 99,101, 0,115,109,111,111,116,104,114,101,115,104, 0,115,117, 98, -100,105,118, 0,115,117, 98,100,105,118,114, 0,115,117, 98,115,117,114,102,116,121,112,101, 0,101,100,105,116,102,108, 97,103, - 0, 42,109,114, 0, 42,116,112, 97,103,101, 0,117,118, 91, 52, 93, 91, 50, 93, 0, 99,111,108, 91, 52, 93, 0,116,114, 97,110, -115,112, 0,116,105,108,101, 0,117,110,119,114, 97,112, 0,118, 49, 0,118, 50, 0,118, 51, 0,118, 52, 0,101,100, 99,111,100, -101, 0, 99,114,101, 97,115,101, 0, 98,119,101,105,103,104,116, 0,100,101,102, 95,110,114, 0, 42,100,119, 0,116,111,116,119, -101,105,103,104,116, 0, 99,111, 91, 51, 93, 0,110,111, 91, 51, 93, 0,108,111,111,112,115,116, 97,114,116, 0,118, 0,101, 0, -117,118, 91, 50, 93, 0, 99,111, 91, 50, 93, 0,102, 0,105, 0,115, 91, 50, 53, 54, 93, 0,116,111,116,100,105,115,112, 0,108, -101,118,101,108, 0, 40, 42,100,105,115,112,115, 41, 40, 41, 0, 42,104,105,100,100,101,110, 0,118, 91, 52, 93, 0,109,105,100, - 0,112, 97,100, 91, 50, 93, 0,118, 91, 50, 93, 0, 42,102, 97, 99,101,115, 0, 42, 99,111,108,102, 97, 99,101,115, 0, 42,101, -100,103,101,115, 0, 42,118,101,114,116,115, 0,108,101,118,101,108,115, 0,108,101,118,101,108, 95, 99,111,117,110,116, 0, 99, -117,114,114,101,110,116, 0,110,101,119,108,118,108, 0,101,100,103,101,108,118,108, 0,112,105,110,108,118,108, 0,114,101,110, -100,101,114,108,118,108, 0,117,115,101, 95, 99,111,108, 0, 42,101,100,103,101, 95,102,108, 97,103,115, 0, 42,101,100,103,101, - 95, 99,114,101, 97,115,101,115, 0,115,116, 97, 99,107,105,110,100,101,120, 0, 42,101,114,114,111,114, 0,109,111,100,105,102, -105,101,114, 0, 42,116,101,120,116,117,114,101, 0, 42,109, 97,112, 95,111, 98,106,101, 99,116, 0,117,118,108, 97,121,101,114, - 95,110, 97,109,101, 91, 54, 52, 93, 0,117,118,108, 97,121,101,114, 95,116,109,112, 0,116,101,120,109, 97,112,112,105,110,103, - 0,115,117, 98,100,105,118, 84,121,112,101, 0,114,101,110,100,101,114, 76,101,118,101,108,115, 0, 42,101,109, 67, 97, 99,104, -101, 0, 42,109, 67, 97, 99,104,101, 0,115,116,114,101,110,103,116,104, 0,100,101,102, 97,120,105,115, 0,112, 97,100, 91, 54, - 93, 0,108,101,110,103,116,104, 0,114, 97,110,100,111,109,105,122,101, 0,115,101,101,100, 0, 42,111, 98, 95, 97,114,109, 0, - 42,115,116, 97,114,116, 95, 99, 97,112, 0, 42,101,110,100, 95, 99, 97,112, 0, 42, 99,117,114,118,101, 95,111, 98, 0, 42,111, -102,102,115,101,116, 95,111, 98, 0,111,102,102,115,101,116, 91, 51, 93, 0,115, 99, 97,108,101, 91, 51, 93, 0,109,101,114,103, -101, 95,100,105,115,116, 0,102,105,116, 95,116,121,112,101, 0,111,102,102,115,101,116, 95,116,121,112,101, 0, 99,111,117,110, -116, 0, 97,120,105,115, 0,116,111,108,101,114, 97,110, 99,101, 0, 42,109,105,114,114,111,114, 95,111, 98, 0,115,112,108,105, -116, 95, 97,110,103,108,101, 0,118, 97,108,117,101, 0,114,101,115, 0,118, 97,108, 95,102,108, 97,103,115, 0,108,105,109, 95, -102,108, 97,103,115, 0,101, 95,102,108, 97,103,115, 0, 98,101,118,101,108, 95, 97,110,103,108,101, 0,100,101,102,103,114,112, - 95,110, 97,109,101, 91, 54, 52, 93, 0, 42,100,111,109, 97,105,110, 0, 42,102,108,111,119, 0, 42, 99,111,108,108, 0,116,105, -109,101, 0,100,105,114,101, 99,116,105,111,110, 0,109,105,100,108,101,118,101,108, 0, 42,112,114,111,106,101, 99,116,111,114, -115, 91, 49, 48, 93, 0, 42,105,109, 97,103,101, 0,110,117,109, 95,112,114,111,106,101, 99,116,111,114,115, 0, 97,115,112,101, - 99,116,120, 0, 97,115,112,101, 99,116,121, 0,115, 99, 97,108,101,120, 0,115, 99, 97,108,101,121, 0,112,101,114, 99,101,110, -116, 0,102, 97, 99,101, 67,111,117,110,116, 0,102, 97, 99, 0,114,101,112,101, 97,116, 0, 42,111, 98,106,101, 99,116, 99,101, -110,116,101,114, 0,115,116, 97,114,116,120, 0,115,116, 97,114,116,121, 0,104,101,105,103,104,116, 0,110, 97,114,114,111,119, - 0,115,112,101,101,100, 0,100, 97,109,112, 0,102, 97,108,108,111,102,102, 0,116,105,109,101,111,102,102,115, 0,108,105,102, -101,116,105,109,101, 0,100,101,102,111,114,109,102,108, 97,103, 0,109,117,108,116,105, 0, 42,112,114,101,118, 67,111,115, 0, -115,117, 98,116, 97,114,103,101,116, 91, 54, 52, 93, 0,112, 97,114,101,110,116,105,110,118, 91, 52, 93, 91, 52, 93, 0, 99,101, -110,116, 91, 51, 93, 0, 42,105,110,100,101,120, 97,114, 0,116,111,116,105,110,100,101,120, 0,102,111,114, 99,101, 0, 42, 99, -108,111,116,104, 79, 98,106,101, 99,116, 0, 42,115,105,109, 95,112, 97,114,109,115, 0, 42, 99,111,108,108, 95,112, 97,114,109, -115, 0, 42,112,111,105,110,116, 95, 99, 97, 99,104,101, 0,112,116, 99, 97, 99,104,101,115, 0, 42,120, 0, 42,120,110,101,119, - 0, 42,120,111,108,100, 0, 42, 99,117,114,114,101,110,116, 95,120,110,101,119, 0, 42, 99,117,114,114,101,110,116, 95,120, 0, - 42, 99,117,114,114,101,110,116, 95,118, 0, 42,109,102, 97, 99,101,115, 0,110,117,109,118,101,114,116,115, 0,110,117,109,102, - 97, 99,101,115, 0,116,105,109,101, 95,120, 0,116,105,109,101, 95,120,110,101,119, 0, 42, 98,118,104,116,114,101,101, 0, 42, -118, 0, 42,100,109, 0, 99,102,114, 97, 0,111,112,101,114, 97,116,105,111,110, 0,118,101,114,116,101,120, 0,116,111,116,105, -110,102,108,117,101,110, 99,101, 0,103,114,105,100,115,105,122,101, 0, 42, 98,105,110,100,105,110,102,108,117,101,110, 99,101, -115, 0, 42, 98,105,110,100,111,102,102,115,101,116,115, 0, 42, 98,105,110,100, 99, 97,103,101, 99,111,115, 0,116,111,116, 99, - 97,103,101,118,101,114,116, 0, 42,100,121,110,103,114,105,100, 0, 42,100,121,110,105,110,102,108,117,101,110, 99,101,115, 0, - 42,100,121,110,118,101,114,116,115, 0, 42,112, 97,100, 50, 0,100,121,110,103,114,105,100,115,105,122,101, 0,100,121,110, 99, -101,108,108,109,105,110, 91, 51, 93, 0,100,121,110, 99,101,108,108,119,105,100,116,104, 0, 98,105,110,100,109, 97,116, 91, 52, - 93, 91, 52, 93, 0, 42, 98,105,110,100,119,101,105,103,104,116,115, 0, 42, 98,105,110,100, 99,111,115, 0, 40, 42, 98,105,110, -100,102,117,110, 99, 41, 40, 41, 0, 42,112,115,121,115, 0,116,111,116,100,109,118,101,114,116, 0,116,111,116,100,109,101,100, -103,101, 0,116,111,116,100,109,102, 97, 99,101, 0,112,111,115,105,116,105,111,110, 0,114, 97,110,100,111,109, 95,112,111,115, -105,116,105,111,110, 0, 42,102, 97, 99,101,112, 97, 0,118,103,114,111,117,112, 0,112,114,111,116,101, 99,116, 0,108,118,108, - 0,115, 99,117,108,112,116,108,118,108, 0,116,111,116,108,118,108, 0,115,105,109,112,108,101, 0, 42,102,115,115, 0, 42,116, - 97,114,103,101,116, 0, 42, 97,117,120, 84, 97,114,103,101,116, 0,118,103,114,111,117,112, 95,110, 97,109,101, 91, 54, 52, 93, - 0,107,101,101,112, 68,105,115,116, 0,115,104,114,105,110,107, 84,121,112,101, 0,115,104,114,105,110,107, 79,112,116,115, 0, -112,114,111,106, 65,120,105,115, 0,115,117, 98,115,117,114,102, 76,101,118,101,108,115, 0, 42,111,114,105,103,105,110, 0,102, - 97, 99,116,111,114, 0,108,105,109,105,116, 91, 50, 93, 0,111,114,105,103,105,110, 79,112,116,115, 0,111,102,102,115,101,116, - 95,102, 97, 99, 0,111,102,102,115,101,116, 95,102, 97, 99, 95,118,103, 0, 99,114,101, 97,115,101, 95,105,110,110,101,114, 0, - 99,114,101, 97,115,101, 95,111,117,116,101,114, 0, 99,114,101, 97,115,101, 95,114,105,109, 0,109, 97,116, 95,111,102,115, 0, -109, 97,116, 95,111,102,115, 95,114,105,109, 0, 42,111, 98, 95, 97,120,105,115, 0,115,116,101,112,115, 0,114,101,110,100,101, -114, 95,115,116,101,112,115, 0,105,116,101,114, 0,115, 99,114,101,119, 95,111,102,115, 0, 97,110,103,108,101, 0, 42,111, 99, -101, 97,110, 0, 42,111, 99,101, 97,110, 99, 97, 99,104,101, 0,114,101,115,111,108,117,116,105,111,110, 0,115,112, 97,116,105, - 97,108, 95,115,105,122,101, 0,119,105,110,100, 95,118,101,108,111, 99,105,116,121, 0,115,109, 97,108,108,101,115,116, 95,119, - 97,118,101, 0,119, 97,118,101, 95, 97,108,105,103,110,109,101,110,116, 0,119, 97,118,101, 95,100,105,114,101, 99,116,105,111, -110, 0,119, 97,118,101, 95,115, 99, 97,108,101, 0, 99,104,111,112, 95, 97,109,111,117,110,116, 0,102,111, 97,109, 95, 99,111, -118,101,114, 97,103,101, 0, 98, 97,107,101,115,116, 97,114,116, 0, 98, 97,107,101,101,110,100, 0, 99, 97, 99,104,101,112, 97, -116,104, 91, 49, 48, 50, 52, 93, 0,102,111, 97,109,108, 97,121,101,114,110, 97,109,101, 91, 54, 52, 93, 0, 99, 97, 99,104,101, -100, 0,103,101,111,109,101,116,114,121, 95,109,111,100,101, 0,114,101,102,114,101,115,104, 0,114,101,112,101, 97,116, 95,120, - 0,114,101,112,101, 97,116, 95,121, 0,102,111, 97,109, 95,102, 97,100,101, 0, 42,111, 98,106,101, 99,116, 95,102,114,111,109, - 0, 42,111, 98,106,101, 99,116, 95,116,111, 0,102, 97,108,108,111,102,102, 95,114, 97,100,105,117,115, 0,101,100,105,116, 95, -102,108, 97,103,115, 0,100,101,102, 97,117,108,116, 95,119,101,105,103,104,116, 0, 42, 99,109, 97,112, 95, 99,117,114,118,101, - 0, 97,100,100, 95,116,104,114,101,115,104,111,108,100, 0,114,101,109, 95,116,104,114,101,115,104,111,108,100, 0,109, 97,115, -107, 95, 99,111,110,115,116, 97,110,116, 0,109, 97,115,107, 95,100,101,102,103,114,112, 95,110, 97,109,101, 91, 54, 52, 93, 0, -109, 97,115,107, 95,116,101,120, 95,117,115,101, 95, 99,104, 97,110,110,101,108, 0, 42,109, 97,115,107, 95,116,101,120,116,117, -114,101, 0, 42,109, 97,115,107, 95,116,101,120, 95,109, 97,112, 95,111, 98,106, 0,109, 97,115,107, 95,116,101,120, 95,109, 97, -112,112,105,110,103, 0,109, 97,115,107, 95,116,101,120, 95,117,118,108, 97,121,101,114, 95,110, 97,109,101, 91, 54, 52, 93, 0, -112, 97,100, 95,105, 49, 0,100,101,102,103,114,112, 95,110, 97,109,101, 95, 97, 91, 54, 52, 93, 0,100,101,102,103,114,112, 95, -110, 97,109,101, 95, 98, 91, 54, 52, 93, 0,100,101,102, 97,117,108,116, 95,119,101,105,103,104,116, 95, 97, 0,100,101,102, 97, -117,108,116, 95,119,101,105,103,104,116, 95, 98, 0,109,105,120, 95,109,111,100,101, 0,109,105,120, 95,115,101,116, 0,112, 97, -100, 95, 99, 49, 91, 54, 93, 0,112,114,111,120,105,109,105,116,121, 95,109,111,100,101, 0,112,114,111,120,105,109,105,116,121, - 95,102,108, 97,103,115, 0, 42,112,114,111,120,105,109,105,116,121, 95,111, 98, 95,116, 97,114,103,101,116, 0,109,105,110, 95, -100,105,115,116, 0,109, 97,120, 95,100,105,115,116, 0,112, 97,100, 95,115, 49, 0, 42, 99, 97,110,118, 97,115, 0, 42, 98,114, -117,115,104, 0,116,104,114,101,115,104,111,108,100, 0,115, 99, 97,108,101, 0,104,101,114,109,105,116,101, 95,110,117,109, 0, - 42,108, 97,116,116, 0,112,110,116,115,119, 0,111,112,110,116,115,117, 0,111,112,110,116,115,118, 0,111,112,110,116,115,119, - 0,116,121,112,101,117, 0,116,121,112,101,118, 0,116,121,112,101,119, 0,102,117, 0,102,118, 0,102,119, 0,100,117, 0,100, -118, 0,100,119, 0, 42,100,101,102, 0, 42,108, 97,116,116,105, 99,101,100, 97,116, 97, 0,108, 97,116,109, 97,116, 91, 52, 93, - 91, 52, 93, 0, 42,101,100,105,116,108, 97,116,116, 0,118,101, 99, 91, 56, 93, 91, 51, 93, 0, 42,115, 99,117,108,112,116, 0, -112, 97,114,116,121,112,101, 0,112, 97,114, 49, 0,112, 97,114, 50, 0,112, 97,114, 51, 0,112, 97,114,115,117, 98,115,116,114, - 91, 54, 52, 93, 0, 42,116,114, 97, 99,107, 0, 42,112,114,111,120,121, 0, 42,112,114,111,120,121, 95,103,114,111,117,112, 0, - 42,112,114,111,120,121, 95,102,114,111,109, 0, 42, 97, 99,116,105,111,110, 0, 42,112,111,115,101,108,105, 98, 0, 42,112,111, -115,101, 0, 42,103,112,100, 0, 97,118,115, 0, 42,109,112, 97,116,104, 0, 99,111,110,115,116,114, 97,105,110,116, 67,104, 97, -110,110,101,108,115, 0,101,102,102,101, 99,116, 0,100,101,102, 98, 97,115,101, 0,109,111,100,105,102,105,101,114,115, 0,114, -101,115,116,111,114,101, 95,109,111,100,101, 0, 42,109, 97,116, 98,105,116,115, 0, 97, 99,116, 99,111,108, 0,100,108,111, 99, - 91, 51, 93, 0,111,114,105,103, 91, 51, 93, 0,100,115,105,122,101, 91, 51, 93, 0,100,115, 99, 97,108,101, 91, 51, 93, 0,100, -114,111,116, 91, 51, 93, 0,100,113,117, 97,116, 91, 52, 93, 0,114,111,116, 65,120,105,115, 91, 51, 93, 0,100,114,111,116, 65, -120,105,115, 91, 51, 93, 0,114,111,116, 65,110,103,108,101, 0,100,114,111,116, 65,110,103,108,101, 0,111, 98,109, 97,116, 91, - 52, 93, 91, 52, 93, 0, 99,111,110,115,116,105,110,118, 91, 52, 93, 91, 52, 93, 0,105,109, 97,116, 95,114,101,110, 91, 52, 93, - 91, 52, 93, 0,108, 97,121, 0,112, 97,100, 54, 0, 99,111,108, 98,105,116,115, 0,116,114, 97,110,115,102,108, 97,103, 0,112, -114,111,116,101, 99,116,102,108, 97,103, 0,116,114, 97, 99,107,102,108, 97,103, 0,117,112,102,108, 97,103, 0,110,108, 97,102, -108, 97,103, 0,105,112,111,102,108, 97,103, 0,115, 99, 97,102,108, 97,103, 0,115, 99, 97,118,105,115,102,108, 97,103, 0,112, - 97,100, 53, 0,100,117,112,111,110, 0,100,117,112,111,102,102, 0,100,117,112,115,116, 97, 0,100,117,112,101,110,100, 0,115, -102, 0,109, 97,115,115, 0,100, 97,109,112,105,110,103, 0,105,110,101,114,116,105, 97, 0,102,111,114,109,102, 97, 99,116,111, -114, 0,114,100, 97,109,112,105,110,103, 0,109, 97,114,103,105,110, 0,109, 97,120, 95,118,101,108, 0,109,105,110, 95,118,101, -108, 0,109, 95, 99,111,110,116, 97, 99,116, 80,114,111, 99,101,115,115,105,110,103, 84,104,114,101,115,104,111,108,100, 0,111, - 98,115,116, 97, 99,108,101, 82, 97,100, 0,114,111,116,109,111,100,101, 0, 98,111,117,110,100,116,121,112,101, 0, 99,111,108, -108,105,115,105,111,110, 95, 98,111,117,110,100,116,121,112,101, 0,114,101,115,116,114,105, 99,116,102,108, 97,103, 0,100,116, - 0,101,109,112,116,121, 95,100,114, 97,119,116,121,112,101, 0,101,109,112,116,121, 95,100,114, 97,119,115,105,122,101, 0,100, -117,112,102, 97, 99,101,115, 99, 97, 0,112,114,111,112, 0,115,101,110,115,111,114,115, 0, 99,111,110,116,114,111,108,108,101, -114,115, 0, 97, 99,116,117, 97,116,111,114,115, 0, 98, 98,115,105,122,101, 91, 51, 93, 0, 97, 99,116,100,101,102, 0,103, 97, -109,101,102,108, 97,103, 0,103, 97,109,101,102,108, 97,103, 50, 0, 42, 98,115,111,102,116, 0,115,111,102,116,102,108, 97,103, - 0, 97,110,105,115,111,116,114,111,112,105, 99, 70,114,105, 99,116,105,111,110, 91, 51, 93, 0, 99,111,110,115,116,114, 97,105, -110,116,115, 0,110,108, 97,115,116,114,105,112,115, 0,104,111,111,107,115, 0,112, 97,114,116,105, 99,108,101,115,121,115,116, -101,109, 0, 42,115,111,102,116, 0, 42,100,117,112, 95,103,114,111,117,112, 0, 98,111,100,121, 95,116,121,112,101, 0,115,104, - 97,112,101,102,108, 97,103, 0, 42,102,108,117,105,100,115,105,109, 83,101,116,116,105,110,103,115, 0, 42,100,101,114,105,118, -101,100, 68,101,102,111,114,109, 0, 42,100,101,114,105,118,101,100, 70,105,110, 97,108, 0,108, 97,115,116, 68, 97,116, 97, 77, - 97,115,107, 0, 99,117,115,116,111,109,100, 97,116, 97, 95,109, 97,115,107, 0,115,116, 97,116,101, 0,105,110,105,116, 95,115, -116, 97,116,101, 0,103,112,117,108, 97,109,112, 0,112, 99, 95,105,100,115, 0, 42,100,117,112,108,105,108,105,115,116, 0,105, -109, 97, 95,111,102,115, 91, 50, 93, 0, 99,117,114,105,110,100,101,120, 0, 97, 99,116,105,118,101, 0,111,114,105,103,108, 97, -121, 0,111,109, 97,116, 91, 52, 93, 91, 52, 93, 0,111,114, 99,111, 91, 51, 93, 0,110,111, 95,100,114, 97,119, 0, 97,110,105, -109, 97,116,101,100, 0,100,101,102,108,101, 99,116, 0,102,111,114, 99,101,102,105,101,108,100, 0,115,104, 97,112,101, 0,116, -101,120, 95,109,111,100,101, 0,107,105,110,107, 0,107,105,110,107, 95, 97,120,105,115, 0,122,100,105,114, 0,102, 95,115,116, -114,101,110,103,116,104, 0,102, 95,100, 97,109,112, 0,102, 95,102,108,111,119, 0,102, 95,115,105,122,101, 0,102, 95,112,111, -119,101,114, 0,109, 97,120,100,105,115,116, 0,109,105,110,100,105,115,116, 0,102, 95,112,111,119,101,114, 95,114, 0,109, 97, -120,114, 97,100, 0,109,105,110,114, 97,100, 0,112,100,101,102, 95,100, 97,109,112, 0,112,100,101,102, 95,114,100, 97,109,112, - 0,112,100,101,102, 95,112,101,114,109, 0,112,100,101,102, 95,102,114,105, 99,116, 0,112,100,101,102, 95,114,102,114,105, 99, -116, 0,112,100,101,102, 95,115,116,105, 99,107,110,101,115,115, 0, 97, 98,115,111,114,112,116,105,111,110, 0,112,100,101,102, - 95,115, 98,100, 97,109,112, 0,112,100,101,102, 95,115, 98,105,102,116, 0,112,100,101,102, 95,115, 98,111,102,116, 0, 99,108, -117,109,112, 95,102, 97, 99, 0, 99,108,117,109,112, 95,112,111,119, 0,107,105,110,107, 95,102,114,101,113, 0,107,105,110,107, - 95,115,104, 97,112,101, 0,107,105,110,107, 95, 97,109,112, 0,102,114,101,101, 95,101,110,100, 0,116,101,120, 95,110, 97, 98, -108, 97, 0, 42,114,110,103, 0,102, 95,110,111,105,115,101, 0,119,101,105,103,104,116, 91, 49, 51, 93, 0,103,108,111, 98, 97, -108, 95,103,114, 97,118,105,116,121, 0,114,116, 91, 51, 93, 0,116,111,116,100, 97,116, 97, 0,102,114, 97,109,101, 0,116,111, -116,112,111,105,110,116, 0,100, 97,116, 97, 95,116,121,112,101,115, 0, 42,100, 97,116, 97, 91, 56, 93, 0, 42, 99,117,114, 91, - 56, 93, 0,101,120,116,114, 97,100, 97,116, 97, 0,115,116,101,112, 0,115,105,109,102,114, 97,109,101, 0,115,116, 97,114,116, -102,114, 97,109,101, 0,101,110,100,102,114, 97,109,101, 0,101,100,105,116,102,114, 97,109,101, 0,108, 97,115,116, 95,101,120, - 97, 99,116, 0,108, 97,115,116, 95,118, 97,108,105,100, 0, 99,111,109,112,114,101,115,115,105,111,110, 0,112,114,101,118, 95, -110, 97,109,101, 91, 54, 52, 93, 0,105,110,102,111, 91, 54, 52, 93, 0,112, 97,116,104, 91, 49, 48, 50, 52, 93, 0, 42, 99, 97, - 99,104,101,100, 95,102,114, 97,109,101,115, 0,109,101,109, 95, 99, 97, 99,104,101, 0, 42,101,100,105,116, 0, 40, 42,102,114, -101,101, 95,101,100,105,116, 41, 40, 41, 0,108,105,110, 83,116,105,102,102, 0, 97,110,103, 83,116,105,102,102, 0,118,111,108, -117,109,101, 0,118,105,116,101,114, 97,116,105,111,110,115, 0,112,105,116,101,114, 97,116,105,111,110,115, 0,100,105,116,101, -114, 97,116,105,111,110,115, 0, 99,105,116,101,114, 97,116,105,111,110,115, 0,107, 83, 82, 72, 82, 95, 67, 76, 0,107, 83, 75, - 72, 82, 95, 67, 76, 0,107, 83, 83, 72, 82, 95, 67, 76, 0,107, 83, 82, 95, 83, 80, 76, 84, 95, 67, 76, 0,107, 83, 75, 95, 83, - 80, 76, 84, 95, 67, 76, 0,107, 83, 83, 95, 83, 80, 76, 84, 95, 67, 76, 0,107, 86, 67, 70, 0,107, 68, 80, 0,107, 68, 71, 0, -107, 76, 70, 0,107, 80, 82, 0,107, 86, 67, 0,107, 68, 70, 0,107, 77, 84, 0,107, 67, 72, 82, 0,107, 75, 72, 82, 0,107, 83, - 72, 82, 0,107, 65, 72, 82, 0, 99,111,108,108,105,115,105,111,110,102,108, 97,103,115, 0,110,117,109, 99,108,117,115,116,101, -114,105,116,101,114, 97,116,105,111,110,115, 0,119,101,108,100,105,110,103, 0,116,111,116,115,112,114,105,110,103, 0, 42, 98, -112,111,105,110,116, 0, 42, 98,115,112,114,105,110,103, 0,109,115,103, 95,108,111, 99,107, 0,109,115,103, 95,118, 97,108,117, -101, 0,110,111,100,101,109, 97,115,115, 0,110, 97,109,101,100, 86, 71, 95, 77, 97,115,115, 91, 54, 52, 93, 0,103,114, 97,118, - 0,109,101,100,105, 97,102,114,105, 99,116, 0,114,107,108,105,109,105,116, 0,112,104,121,115,105, 99,115, 95,115,112,101,101, -100, 0,103,111, 97,108,115,112,114,105,110,103, 0,103,111, 97,108,102,114,105, 99,116, 0,109,105,110,103,111, 97,108, 0,109, - 97,120,103,111, 97,108, 0,100,101,102,103,111, 97,108, 0,118,101,114,116,103,114,111,117,112, 0,110, 97,109,101,100, 86, 71, - 95, 83,111,102,116,103,111, 97,108, 91, 54, 52, 93, 0,102,117,122,122,121,110,101,115,115, 0,105,110,115,112,114,105,110,103, - 0,105,110,102,114,105, 99,116, 0,110, 97,109,101,100, 86, 71, 95, 83,112,114,105,110,103, 95, 75, 91, 54, 52, 93, 0,101,102, -114, 97, 0,105,110,116,101,114,118, 97,108, 0,108,111, 99, 97,108, 0,115,111,108,118,101,114,102,108, 97,103,115, 0, 42, 42, -107,101,121,115, 0,116,111,116,112,111,105,110,116,107,101,121, 0,115,101, 99,111,110,100,115,112,114,105,110,103, 0, 99,111, -108, 98, 97,108,108, 0, 98, 97,108,108,100, 97,109,112, 0, 98, 97,108,108,115,116,105,102,102, 0,115, 98, 99, 95,109,111,100, -101, 0, 97,101,114,111,101,100,103,101, 0,109,105,110,108,111,111,112,115, 0,109, 97,120,108,111,111,112,115, 0, 99,104,111, -107,101, 0,115,111,108,118,101,114, 95, 73, 68, 0,112,108, 97,115,116,105, 99, 0,115,112,114,105,110,103,112,114,101,108,111, - 97,100, 0, 42,115, 99,114, 97,116, 99,104, 0,115,104,101, 97,114,115,116,105,102,102, 0,105,110,112,117,115,104, 0, 42,112, -111,105,110,116, 99, 97, 99,104,101, 0, 42,101,102,102,101, 99,116,111,114, 95,119,101,105,103,104,116,115, 0,108, 99,111,109, - 91, 51, 93, 0,108,114,111,116, 91, 51, 93, 91, 51, 93, 0,108,115, 99, 97,108,101, 91, 51, 93, 91, 51, 93, 0,108, 97,115,116, - 95,102,114, 97,109,101, 0,118,101,108, 91, 51, 93, 0, 42,102,109,100, 0,115,104,111,119, 95, 97,100,118, 97,110, 99,101,100, -111,112,116,105,111,110,115, 0,114,101,115,111,108,117,116,105,111,110,120,121,122, 0,112,114,101,118,105,101,119,114,101,115, -120,121,122, 0,114,101, 97,108,115,105,122,101, 0,103,117,105, 68,105,115,112,108, 97,121, 77,111,100,101, 0,114,101,110,100, -101,114, 68,105,115,112,108, 97,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 86, 97,108,117,101, 0,118,105,115, - 99,111,115,105,116,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 69,120,112,111,110,101,110,116, 0,103,114, 97, -118, 91, 51, 93, 0, 97,110,105,109, 83,116, 97,114,116, 0, 97,110,105,109, 69,110,100, 0, 98, 97,107,101, 83,116, 97,114,116, - 0, 98, 97,107,101, 69,110,100, 0,102,114, 97,109,101, 79,102,102,115,101,116, 0,103,115,116, 97,114, 0,109, 97,120, 82,101, -102,105,110,101, 0,105,110,105, 86,101,108,120, 0,105,110,105, 86,101,108,121, 0,105,110,105, 86,101,108,122, 0, 42,111,114, -103, 77,101,115,104, 0, 42,109,101,115,104, 66, 66, 0,115,117,114,102,100, 97,116, 97, 80, 97,116,104, 91, 49, 48, 50, 52, 93, - 0, 98, 98, 83,116, 97,114,116, 91, 51, 93, 0, 98, 98, 83,105,122,101, 91, 51, 93, 0,116,121,112,101, 70,108, 97,103,115, 0, -100,111,109, 97,105,110, 78,111,118,101, 99,103,101,110, 0,118,111,108,117,109,101, 73,110,105,116, 84,121,112,101, 0,112, 97, -114,116, 83,108,105,112, 86, 97,108,117,101, 0,103,101,110,101,114, 97,116,101, 84,114, 97, 99,101,114,115, 0,103,101,110,101, -114, 97,116,101, 80, 97,114,116,105, 99,108,101,115, 0,115,117,114,102, 97, 99,101, 83,109,111,111,116,104,105,110,103, 0,115, -117,114,102, 97, 99,101, 83,117, 98,100,105,118,115, 0,112, 97,114,116,105, 99,108,101, 73,110,102, 83,105,122,101, 0,112, 97, -114,116,105, 99,108,101, 73,110,102, 65,108,112,104, 97, 0,102, 97,114, 70,105,101,108,100, 83,105,122,101, 0, 42,109,101,115, -104, 86,101,108,111, 99,105,116,105,101,115, 0, 99,112,115, 84,105,109,101, 83,116, 97,114,116, 0, 99,112,115, 84,105,109,101, - 69,110,100, 0, 99,112,115, 81,117, 97,108,105,116,121, 0, 97,116,116,114, 97, 99,116,102,111,114, 99,101, 83,116,114,101,110, -103,116,104, 0, 97,116,116,114, 97, 99,116,102,111,114, 99,101, 82, 97,100,105,117,115, 0,118,101,108,111, 99,105,116,121,102, -111,114, 99,101, 83,116,114,101,110,103,116,104, 0,118,101,108,111, 99,105,116,121,102,111,114, 99,101, 82, 97,100,105,117,115, - 0,108, 97,115,116,103,111,111,100,102,114, 97,109,101, 0, 97,110,105,109, 82, 97,116,101, 0,109,105,115,116,121,112,101, 0, -104,111,114,114, 0,104,111,114,103, 0,104,111,114, 98, 0,122,101,110,114, 0,122,101,110,103, 0,122,101,110, 98, 0,102, 97, -115,116, 99,111,108, 0,101,120,112,111,115,117,114,101, 0,101,120,112, 0,114, 97,110,103,101, 0,108,105,110,102, 97, 99, 0, -108,111,103,102, 97, 99, 0,103,114, 97,118,105,116,121, 0, 97, 99,116,105,118,105,116,121, 66,111,120, 82, 97,100,105,117,115, - 0,115,107,121,116,121,112,101, 0,111, 99, 99,108,117,115,105,111,110, 82,101,115, 0,112,104,121,115,105, 99,115, 69,110,103, -105,110,101, 0,116,105, 99,114, 97,116,101, 0,109, 97,120,108,111,103,105, 99,115,116,101,112, 0,112,104,121,115,117, 98,115, -116,101,112, 0,109, 97,120,112,104,121,115,116,101,112, 0,109,105,115,105, 0,109,105,115,116,115,116, 97, 0,109,105,115,116, -100,105,115,116, 0,109,105,115,116,104,105, 0,115,116, 97,114,114, 0,115,116, 97,114,103, 0,115,116, 97,114, 98, 0,115,116, - 97,114,107, 0,115,116, 97,114,115,105,122,101, 0,115,116, 97,114,109,105,110,100,105,115,116, 0,115,116, 97,114,100,105,115, -116, 0,115,116, 97,114, 99,111,108,110,111,105,115,101, 0,100,111,102,115,116, 97, 0,100,111,102,101,110,100, 0,100,111,102, -109,105,110, 0,100,111,102,109, 97,120, 0, 97,111,100,105,115,116, 0, 97,111,100,105,115,116,102, 97, 99, 0, 97,111,101,110, -101,114,103,121, 0, 97,111, 98,105, 97,115, 0, 97,111,109,111,100,101, 0, 97,111,115, 97,109,112, 0, 97,111,109,105,120, 0, - 97,111, 99,111,108,111,114, 0, 97,111, 95, 97,100, 97,112,116, 95,116,104,114,101,115,104, 0, 97,111, 95, 97,100, 97,112,116, - 95,115,112,101,101,100, 95,102, 97, 99, 0, 97,111, 95, 97,112,112,114,111,120, 95,101,114,114,111,114, 0, 97,111, 95, 97,112, -112,114,111,120, 95, 99,111,114,114,101, 99,116,105,111,110, 0, 97,111, 95,105,110,100,105,114,101, 99,116, 95,101,110,101,114, -103,121, 0, 97,111, 95,101,110,118, 95,101,110,101,114,103,121, 0, 97,111, 95,112, 97,100, 50, 0, 97,111, 95,105,110,100,105, -114,101, 99,116, 95, 98,111,117,110, 99,101,115, 0, 97,111, 95,112, 97,100, 0, 97,111, 95,115, 97,109,112, 95,109,101,116,104, -111,100, 0, 97,111, 95,103, 97,116,104,101,114, 95,109,101,116,104,111,100, 0, 97,111, 95, 97,112,112,114,111,120, 95,112, 97, -115,115,101,115, 0, 42, 97,111,115,112,104,101,114,101, 0, 42, 97,111,116, 97, 98,108,101,115, 0,115,101,108, 99,111,108, 0, -115,120, 0,115,121, 0, 42,108,112, 70,111,114,109, 97,116, 0, 42,108,112, 80, 97,114,109,115, 0, 99, 98, 70,111,114,109, 97, -116, 0, 99, 98, 80, 97,114,109,115, 0,102, 99, 99, 84,121,112,101, 0,102, 99, 99, 72, 97,110,100,108,101,114, 0,100,119, 75, -101,121, 70,114, 97,109,101, 69,118,101,114,121, 0,100,119, 81,117, 97,108,105,116,121, 0,100,119, 66,121,116,101,115, 80,101, -114, 83,101, 99,111,110,100, 0,100,119, 70,108, 97,103,115, 0,100,119, 73,110,116,101,114,108,101, 97,118,101, 69,118,101,114, -121, 0, 97,118,105, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, 42, 99,100, 80, 97,114,109,115, 0, 42,112, 97, -100, 0, 99,100, 83,105,122,101, 0,113,116, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, 99,111,100,101, 99, 84, -121,112,101, 0, 99,111,100,101, 99, 83,112, 97,116,105, 97,108, 81,117, 97,108,105,116,121, 0, 99,111,100,101, 99, 0, 99,111, -100,101, 99, 70,108, 97,103,115, 0, 99,111,108,111,114, 68,101,112,116,104, 0, 99,111,100,101, 99, 84,101,109,112,111,114, 97, -108, 81,117, 97,108,105,116,121, 0,109,105,110, 83,112, 97,116,105, 97,108, 81,117, 97,108,105,116,121, 0,109,105,110, 84,101, -109,112,111,114, 97,108, 81,117, 97,108,105,116,121, 0,107,101,121, 70,114, 97,109,101, 82, 97,116,101, 0, 98,105,116, 82, 97, -116,101, 0, 97,117,100,105,111, 99,111,100,101, 99, 84,121,112,101, 0, 97,117,100,105,111, 83, 97,109,112,108,101, 82, 97,116, -101, 0, 97,117,100,105,111, 66,105,116, 68,101,112,116,104, 0, 97,117,100,105,111, 67,104, 97,110,110,101,108,115, 0, 97,117, -100,105,111, 67,111,100,101, 99, 70,108, 97,103,115, 0, 97,117,100,105,111, 66,105,116, 82, 97,116,101, 0, 97,117,100,105,111, - 95, 99,111,100,101, 99, 0,118,105,100,101,111, 95, 98,105,116,114, 97,116,101, 0, 97,117,100,105,111, 95, 98,105,116,114, 97, -116,101, 0, 97,117,100,105,111, 95,109,105,120,114, 97,116,101, 0, 97,117,100,105,111, 95, 99,104, 97,110,110,101,108,115, 0, - 97,117,100,105,111, 95,112, 97,100, 0, 97,117,100,105,111, 95,118,111,108,117,109,101, 0,103,111,112, 95,115,105,122,101, 0, -114, 99, 95,109,105,110, 95,114, 97,116,101, 0,114, 99, 95,109, 97,120, 95,114, 97,116,101, 0,114, 99, 95, 98,117,102,102,101, -114, 95,115,105,122,101, 0,109,117,120, 95,112, 97, 99,107,101,116, 95,115,105,122,101, 0,109,117,120, 95,114, 97,116,101, 0, -109,105,120,114, 97,116,101, 0,109, 97,105,110, 0,115,112,101,101,100, 95,111,102, 95,115,111,117,110,100, 0,100,111,112,112, -108,101,114, 95,102, 97, 99,116,111,114, 0,100,105,115,116, 97,110, 99,101, 95,109,111,100,101,108, 0, 42,109, 97,116, 95,111, -118,101,114,114,105,100,101, 0, 42,108,105,103,104,116, 95,111,118,101,114,114,105,100,101, 0,108, 97,121, 95,122,109, 97,115, -107, 0,108, 97,121,102,108, 97,103, 0,112, 97,115,115,102,108, 97,103, 0,112, 97,115,115, 95,120,111,114, 0,105,109,116,121, -112,101, 0,112,108, 97,110,101,115, 0,113,117, 97,108,105,116,121, 0, 99,111,109,112,114,101,115,115, 0,101,120,114, 95, 99, -111,100,101, 99, 0, 99,105,110,101,111,110, 95,102,108, 97,103, 0, 99,105,110,101,111,110, 95,119,104,105,116,101, 0, 99,105, -110,101,111,110, 95, 98,108, 97, 99,107, 0, 99,105,110,101,111,110, 95,103, 97,109,109, 97, 0,106,112, 50, 95,102,108, 97,103, - 0,105,109, 95,102,111,114,109, 97,116, 0, 42, 97,118,105, 99,111,100,101, 99,100, 97,116, 97, 0, 42,113,116, 99,111,100,101, - 99,100, 97,116, 97, 0,113,116, 99,111,100,101, 99,115,101,116,116,105,110,103,115, 0,102,102, 99,111,100,101, 99,100, 97,116, - 97, 0,115,117, 98,102,114, 97,109,101, 0,112,115,102,114, 97, 0,112,101,102,114, 97, 0,105,109, 97,103,101,115, 0,102,114, - 97,109, 97,112,116,111, 0,116,104,114,101, 97,100,115, 0,102,114, 97,109,101,108,101,110, 0, 98,108,117,114,102, 97, 99, 0, -101,100,103,101, 82, 0,101,100,103,101, 71, 0,101,100,103,101, 66, 0,102,117,108,108,115, 99,114,101,101,110, 0,120,112,108, - 97,121, 0,121,112,108, 97,121, 0,102,114,101,113,112,108, 97,121, 0, 97,116,116,114,105, 98, 0,102,114, 97,109,101, 95,115, -116,101,112, 0,115,116,101,114,101,111,109,111,100,101, 0,100,105,109,101,110,115,105,111,110,115,112,114,101,115,101,116, 0, -109, 97,120,105,109,115,105,122,101, 0,120,115, 99,104, 0,121,115, 99,104, 0,120,112, 97,114,116,115, 0,121,112, 97,114,116, -115, 0,115,117, 98,105,109,116,121,112,101, 0,100,105,115,112,108, 97,121,109,111,100,101, 0,115, 99,101,109,111,100,101, 0, -114, 97,121,116,114, 97, 99,101, 95,111,112,116,105,111,110,115, 0,114, 97,121,116,114, 97, 99,101, 95,115,116,114,117, 99,116, -117,114,101, 0,111, 99,114,101,115, 0,112, 97,100, 52, 0, 97,108,112,104, 97,109,111,100,101, 0,111,115, 97, 0,102,114,115, - 95,115,101, 99, 0,101,100,103,101,105,110,116, 0,115, 97,102,101,116,121, 0, 98,111,114,100,101,114, 0,100,105,115,112,114, -101, 99,116, 0,108, 97,121,101,114,115, 0, 97, 99,116,108, 97,121, 0,109, 98,108,117,114, 95,115, 97,109,112,108,101,115, 0, -120, 97,115,112, 0,121, 97,115,112, 0,102,114,115, 95,115,101, 99, 95, 98, 97,115,101, 0,103, 97,117,115,115, 0, 99,111,108, -111,114, 95,109,103,116, 95,102,108, 97,103, 0,112,111,115,116,103, 97,109,109, 97, 0,112,111,115,116,104,117,101, 0,112,111, -115,116,115, 97,116, 0,100,105,116,104,101,114, 95,105,110,116,101,110,115,105,116,121, 0, 98, 97,107,101, 95,111,115, 97, 0, - 98, 97,107,101, 95,102,105,108,116,101,114, 0, 98, 97,107,101, 95,109,111,100,101, 0, 98, 97,107,101, 95,102,108, 97,103, 0, - 98, 97,107,101, 95,110,111,114,109, 97,108, 95,115,112, 97, 99,101, 0, 98, 97,107,101, 95,113,117, 97,100, 95,115,112,108,105, -116, 0, 98, 97,107,101, 95,109, 97,120,100,105,115,116, 0, 98, 97,107,101, 95, 98,105, 97,115,100,105,115,116, 0, 98, 97,107, -101, 95,112, 97,100, 0,112,105, 99, 91, 49, 48, 50, 52, 93, 0,115,116, 97,109,112, 0,115,116, 97,109,112, 95,102,111,110,116, - 95,105,100, 0,115,116, 97,109,112, 95,117,100, 97,116, 97, 91, 55, 54, 56, 93, 0,102,103, 95,115,116, 97,109,112, 91, 52, 93, - 0, 98,103, 95,115,116, 97,109,112, 91, 52, 93, 0,115,101,113, 95,112,114,101,118, 95,116,121,112,101, 0,115,101,113, 95,114, -101,110,100, 95,116,121,112,101, 0,115,101,113, 95,102,108, 97,103, 0,112, 97,100, 53, 91, 53, 93, 0,115,105,109,112,108,105, -102,121, 95,102,108, 97,103, 0,115,105,109,112,108,105,102,121, 95,115,117, 98,115,117,114,102, 0,115,105,109,112,108,105,102, -121, 95,115,104, 97,100,111,119,115, 97,109,112,108,101,115, 0,115,105,109,112,108,105,102,121, 95,112, 97,114,116,105, 99,108, -101,115, 0,115,105,109,112,108,105,102,121, 95, 97,111,115,115,115, 0, 99,105,110,101,111,110,119,104,105,116,101, 0, 99,105, -110,101,111,110, 98,108, 97, 99,107, 0, 99,105,110,101,111,110,103, 97,109,109, 97, 0,106,112, 50, 95,112,114,101,115,101,116, - 0,106,112, 50, 95,100,101,112,116,104, 0,114,112, 97,100, 51, 0,100,111,109,101,114,101,115, 0,100,111,109,101,109,111,100, -101, 0,100,111,109,101, 97,110,103,108,101, 0,100,111,109,101,116,105,108,116, 0,100,111,109,101,114,101,115, 98,117,102, 0, - 42,100,111,109,101,116,101,120,116, 0,101,110,103,105,110,101, 91, 51, 50, 93, 0,110, 97,109,101, 91, 51, 50, 93, 0,112, 97, -114,116,105, 99,108,101, 95,112,101,114, 99, 0,115,117, 98,115,117,114,102, 95,109, 97,120, 0,115,104, 97,100, 98,117,102,115, - 97,109,112,108,101, 95,109, 97,120, 0, 97,111, 95,101,114,114,111,114, 0,116,105,108,116, 0,114,101,115, 98,117,102, 0, 42, -119, 97,114,112,116,101,120,116, 0, 99,111,108, 91, 51, 93, 0, 99,101,108,108,115,105,122,101, 0, 99,101,108,108,104,101,105, -103,104,116, 0, 97,103,101,110,116,109, 97,120,115,108,111,112,101, 0, 97,103,101,110,116,109, 97,120, 99,108,105,109, 98, 0, - 97,103,101,110,116,104,101,105,103,104,116, 0, 97,103,101,110,116,114, 97,100,105,117,115, 0,101,100,103,101,109, 97,120,108, -101,110, 0,101,100,103,101,109, 97,120,101,114,114,111,114, 0,114,101,103,105,111,110,109,105,110,115,105,122,101, 0,114,101, -103,105,111,110,109,101,114,103,101,115,105,122,101, 0,118,101,114,116,115,112,101,114,112,111,108,121, 0,100,101,116, 97,105, -108,115, 97,109,112,108,101,100,105,115,116, 0,100,101,116, 97,105,108,115, 97,109,112,108,101,109, 97,120,101,114,114,111,114, - 0,102,114, 97,109,105,110,103, 0,112,108, 97,121,101,114,102,108, 97,103, 0,114,116, 49, 0,114,116, 50, 0, 97, 97,115, 97, -109,112,108,101,115, 0,112, 97,100, 52, 91, 51, 93, 0,100,111,109,101, 0,115,116,101,114,101,111,102,108, 97,103, 0,101,121, -101,115,101,112, 97,114, 97,116,105,111,110, 0,114,101, 99, 97,115,116, 68, 97,116, 97, 0,109, 97,116,109,111,100,101, 0,101, -120,105,116,107,101,121, 0,111, 98,115,116, 97, 99,108,101, 83,105,109,117,108, 97,116,105,111,110, 0,108,101,118,101,108, 72, -101,105,103,104,116, 0, 42, 99, 97,109,101,114, 97, 0, 42,112, 97,105,110,116, 95, 99,117,114,115,111,114, 0,112, 97,105,110, -116, 95, 99,117,114,115,111,114, 95, 99,111,108, 91, 52, 93, 0,112, 97,105,110,116, 0,115,101, 97,109, 95, 98,108,101,101,100, - 0,110,111,114,109, 97,108, 95, 97,110,103,108,101, 0,115, 99,114,101,101,110, 95,103,114, 97, 98, 95,115,105,122,101, 91, 50, - 93, 0, 42,112, 97,105,110,116, 99,117,114,115,111,114, 0,105,110,118,101,114,116, 0,116,111,116,114,101,107,101,121, 0,116, -111,116, 97,100,100,107,101,121, 0, 98,114,117,115,104,116,121,112,101, 0, 98,114,117,115,104, 91, 55, 93, 0,101,109,105,116, -116,101,114,100,105,115,116, 0,115,101,108,101, 99,116,109,111,100,101, 0,101,100,105,116,116,121,112,101, 0,100,114, 97,119, - 95,115,116,101,112, 0,102, 97,100,101, 95,102,114, 97,109,101,115, 0,114, 97,100,105, 97,108, 95,115,121,109,109, 91, 51, 93, - 0,108, 97,115,116, 95,120, 0,108, 97,115,116, 95,121, 0,108, 97,115,116, 95, 97,110,103,108,101, 0,100,114, 97,119, 95, 97, -110, 99,104,111,114,101,100, 0, 97,110, 99,104,111,114,101,100, 95,115,105,122,101, 0, 97,110, 99,104,111,114,101,100, 95,108, -111, 99, 97,116,105,111,110, 91, 51, 93, 0, 97,110, 99,104,111,114,101,100, 95,105,110,105,116,105, 97,108, 95,109,111,117,115, -101, 91, 50, 93, 0,100,114, 97,119, 95,112,114,101,115,115,117,114,101, 0,112,114,101,115,115,117,114,101, 95,118, 97,108,117, -101, 0,115,112,101, 99,105, 97,108, 95,114,111,116, 97,116,105,111,110, 0, 42,118,112, 97,105,110,116, 95,112,114,101,118, 0, - 42,119,112, 97,105,110,116, 95,112,114,101,118, 0,109, 97,116, 91, 51, 93, 91, 51, 93, 0,117,110,112,114,111,106,101, 99,116, -101,100, 95,114, 97,100,105,117,115, 0, 42,118,112, 97,105,110,116, 0, 42,119,112, 97,105,110,116, 0, 42,117,118,115, 99,117, -108,112,116, 0,118,103,114,111,117,112, 95,119,101,105,103,104,116, 0, 99,111,114,110,101,114,116,121,112,101, 0,101,100,105, -116, 98,117,116,102,108, 97,103, 0,106,111,105,110,116,114,105,108,105,109,105,116, 0,100,101,103,114, 0,116,117,114,110, 0, -101,120,116,114, 95,111,102,102,115, 0,100,111,117, 98,108,105,109,105,116, 0,110,111,114,109, 97,108,115,105,122,101, 0, 97, -117,116,111,109,101,114,103,101, 0,115,101,103,109,101,110,116,115, 0,114,105,110,103,115, 0,118,101,114,116,105, 99,101,115, - 0,117,110,119,114, 97,112,112,101,114, 0,117,118, 99, 97,108, 99, 95,114, 97,100,105,117,115, 0,117,118, 99, 97,108, 99, 95, - 99,117, 98,101,115,105,122,101, 0,117,118, 99, 97,108, 99, 95,109, 97,114,103,105,110, 0,117,118, 99, 97,108, 99, 95,109, 97, -112,100,105,114, 0,117,118, 99, 97,108, 99, 95,109, 97,112, 97,108,105,103,110, 0,117,118, 99, 97,108, 99, 95,102,108, 97,103, - 0,117,118, 95,102,108, 97,103, 0,117,118, 95,115,101,108,101, 99,116,109,111,100,101, 0,117,118, 95,115,117, 98,115,117,114, -102, 95,108,101,118,101,108, 0,103,112,101,110, 99,105,108, 95,102,108, 97,103,115, 0, 97,117,116,111,105,107, 95, 99,104, 97, -105,110,108,101,110, 0,105,109, 97,112, 97,105,110,116, 0,112, 97,114,116,105, 99,108,101, 0,112,114,111,112,111,114,116,105, -111,110, 97,108, 95,115,105,122,101, 0,115,101,108,101, 99,116, 95,116,104,114,101,115,104, 0, 99,108,101, 97,110, 95,116,104, -114,101,115,104, 0, 97,117,116,111,107,101,121, 95,109,111,100,101, 0, 97,117,116,111,107,101,121, 95,102,108, 97,103, 0,109, -117,108,116,105,114,101,115, 95,115,117, 98,100,105,118, 95,116,121,112,101, 0,112, 97,100, 50, 91, 53, 93, 0,115,107,103,101, -110, 95,114,101,115,111,108,117,116,105,111,110, 0,115,107,103,101,110, 95,116,104,114,101,115,104,111,108,100, 95,105,110,116, -101,114,110, 97,108, 0,115,107,103,101,110, 95,116,104,114,101,115,104,111,108,100, 95,101,120,116,101,114,110, 97,108, 0,115, -107,103,101,110, 95,108,101,110,103,116,104, 95,114, 97,116,105,111, 0,115,107,103,101,110, 95,108,101,110,103,116,104, 95,108, -105,109,105,116, 0,115,107,103,101,110, 95, 97,110,103,108,101, 95,108,105,109,105,116, 0,115,107,103,101,110, 95, 99,111,114, -114,101,108, 97,116,105,111,110, 95,108,105,109,105,116, 0,115,107,103,101,110, 95,115,121,109,109,101,116,114,121, 95,108,105, -109,105,116, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95, 97,110,103,108,101, 95,119,101,105,103,104,116, 0, -115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,108,101,110,103,116,104, 95,119,101,105,103,104,116, 0,115,107,103, -101,110, 95,114,101,116, 97,114,103,101,116, 95,100,105,115,116, 97,110, 99,101, 95,119,101,105,103,104,116, 0,115,107,103,101, -110, 95,111,112,116,105,111,110,115, 0,115,107,103,101,110, 95,112,111,115,116,112,114,111, 0,115,107,103,101,110, 95,112,111, -115,116,112,114,111, 95,112, 97,115,115,101,115, 0,115,107,103,101,110, 95,115,117, 98,100,105,118,105,115,105,111,110,115, 91, - 51, 93, 0,115,107,103,101,110, 95,109,117,108,116,105, 95,108,101,118,101,108, 0, 42,115,107,103,101,110, 95,116,101,109,112, -108, 97,116,101, 0, 98,111,110,101, 95,115,107,101,116, 99,104,105,110,103, 0, 98,111,110,101, 95,115,107,101,116, 99,104,105, -110,103, 95, 99,111,110,118,101,114,116, 0,115,107,103,101,110, 95,115,117, 98,100,105,118,105,115,105,111,110, 95,110,117,109, - 98,101,114, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,111,112,116,105,111,110,115, 0,115,107,103,101,110, - 95,114,101,116, 97,114,103,101,116, 95,114,111,108,108, 0,115,107,103,101,110, 95,115,105,100,101, 95,115,116,114,105,110,103, - 91, 56, 93, 0,115,107,103,101,110, 95,110,117,109, 95,115,116,114,105,110,103, 91, 56, 93, 0,101,100,103,101, 95,109,111,100, -101, 0,101,100,103,101, 95,109,111,100,101, 95,108,105,118,101, 95,117,110,119,114, 97,112, 0,115,110, 97,112, 95,109,111,100, -101, 0,115,110, 97,112, 95,102,108, 97,103, 0,115,110, 97,112, 95,116, 97,114,103,101,116, 0,112,114,111,112,111,114,116,105, -111,110, 97,108, 0,112,114,111,112, 95,109,111,100,101, 0,112,114,111,112,111,114,116,105,111,110, 97,108, 95,111, 98,106,101, - 99,116,115, 0,112, 97,100, 91, 53, 93, 0, 97,117,116,111, 95,110,111,114,109, 97,108,105,122,101, 0,109,117,108,116,105,112, - 97,105,110,116, 0,117,115,101, 95,117,118, 95,115, 99,117,108,112,116, 0,117,118, 95,115, 99,117,108,112,116, 95,115,101,116, -116,105,110,103,115, 0,117,118, 95,115, 99,117,108,112,116, 95,116,111,111,108, 0,117,118, 95,114,101,108, 97,120, 95,109,101, -116,104,111,100, 0,115, 99,117,108,112,116, 95,112, 97,105,110,116, 95,115,101,116,116,105,110,103,115, 0,115, 99,117,108,112, -116, 95,112, 97,105,110,116, 95,117,110,105,102,105,101,100, 95,115,105,122,101, 0,115, 99,117,108,112,116, 95,112, 97,105,110, -116, 95,117,110,105,102,105,101,100, 95,117,110,112,114,111,106,101, 99,116,101,100, 95,114, 97,100,105,117,115, 0,115, 99,117, -108,112,116, 95,112, 97,105,110,116, 95,117,110,105,102,105,101,100, 95, 97,108,112,104, 97, 0,117,110,105,102,105,101,100, 95, -112, 97,105,110,116, 95,115,101,116,116,105,110,103,115, 0,116,111,116,111, 98,106, 0,116,111,116,108, 97,109,112, 0,116,111, -116,111, 98,106,115,101,108, 0,116,111,116, 99,117,114,118,101, 0,116,111,116,109,101,115,104, 0,116,111,116, 97,114,109, 97, -116,117,114,101, 0,115, 99, 97,108,101, 95,108,101,110,103,116,104, 0,115,121,115,116,101,109, 0,115,121,115,116,101,109, 95, -114,111,116, 97,116,105,111,110, 0,103,114, 97,118,105,116,121, 91, 51, 93, 0,113,117,105, 99,107, 95, 99, 97, 99,104,101, 95, -115,116,101,112, 0, 42,119,111,114,108,100, 0, 42,115,101,116, 0, 98, 97,115,101, 0, 42, 98, 97,115, 97, 99,116, 0, 42,111, - 98,101,100,105,116, 0, 99,117,114,115,111,114, 91, 51, 93, 0,116,119, 99,101,110,116, 91, 51, 93, 0,116,119,109,105,110, 91, - 51, 93, 0,116,119,109, 97,120, 91, 51, 93, 0,108, 97,121, 97, 99,116, 0,108, 97,121, 95,117,112,100, 97,116,101,100, 0, 42, -101,100, 0, 42,116,111,111,108,115,101,116,116,105,110,103,115, 0, 42,115,116, 97,116,115, 0, 97,117,100,105,111, 0,116,114, - 97,110,115,102,111,114,109, 95,115,112, 97, 99,101,115, 0, 42,115,111,117,110,100, 95,115, 99,101,110,101, 0, 42,115,111,117, -110,100, 95,115, 99,101,110,101, 95,104, 97,110,100,108,101, 0, 42,115,111,117,110,100, 95,115, 99,114,117, 98, 95,104, 97,110, -100,108,101, 0, 42,115,112,101, 97,107,101,114, 95,104, 97,110,100,108,101,115, 0, 42,102,112,115, 95,105,110,102,111, 0, 42, -116,104,101, 68, 97,103, 0,100, 97,103,105,115,118, 97,108,105,100, 0,100, 97,103,102,108, 97,103,115, 0, 97, 99,116,105,118, -101, 95,107,101,121,105,110,103,115,101,116, 0,107,101,121,105,110,103,115,101,116,115, 0,103,109, 0,117,110,105,116, 0,112, -104,121,115,105, 99,115, 95,115,101,116,116,105,110,103,115, 0, 42, 99,108,105,112, 0, 99,117,115,116,111,109,100, 97,116, 97, - 95,109, 97,115,107, 95,109,111,100, 97,108, 0, 99,117,115,101,114, 0, 98,108,101,110,100, 0,118,105,101,119, 0,119,105,110, -109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,105,110,118, 91, - 52, 93, 91, 52, 93, 0,112,101,114,115,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,101,114,115,105,110,118, 91, 52, 93, 91, 52, - 93, 0,118,105,101,119,109, 97,116,111, 98, 91, 52, 93, 91, 52, 93, 0,112,101,114,115,109, 97,116,111, 98, 91, 52, 93, 91, 52, - 93, 0, 99,108,105,112, 91, 54, 93, 91, 52, 93, 0, 99,108,105,112, 95,108,111, 99, 97,108, 91, 54, 93, 91, 52, 93, 0, 42, 99, -108,105,112, 98, 98, 0, 42,108,111, 99, 97,108,118,100, 0, 42,114,105, 0, 42,114,101,110,100,101,114, 95,101,110,103,105,110, -101, 0, 42,100,101,112,116,104,115, 0, 42,115,109,115, 0, 42,115,109,111,111,116,104, 95,116,105,109,101,114, 0,116,119,109, - 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,113,117, 97,116, 91, 52, 93, 0,122,102, 97, 99, 0, 99, 97,109,100,120, 0, - 99, 97,109,100,121, 0,112,105,120,115,105,122,101, 0, 99, 97,109,122,111,111,109, 0,105,115, 95,112,101,114,115,112, 0,112, -101,114,115,112, 0,118,105,101,119,108,111, 99,107, 0,116,119,100,114, 97,119,102,108, 97,103, 0,114,102,108, 97,103, 0,108, -118,105,101,119,113,117, 97,116, 91, 52, 93, 0,108,112,101,114,115,112, 0,108,118,105,101,119, 0,103,114,105,100,118,105,101, -119, 0,116,119, 97,110,103,108,101, 91, 51, 93, 0,114,111,116, 95, 97,110,103,108,101, 0,114,111,116, 95, 97,120,105,115, 91, - 51, 93, 0,114,101,103,105,111,110, 98, 97,115,101, 0,115,112, 97, 99,101,116,121,112,101, 0, 98,108,111, 99,107,115, 99, 97, -108,101, 0, 98,108,111, 99,107,104, 97,110,100,108,101,114, 91, 56, 93, 0, 98,117,110,100,108,101, 95,115,105,122,101, 0, 98, -117,110,100,108,101, 95,100,114, 97,119,116,121,112,101, 0,108, 97,121, 95,117,115,101,100, 0, 42,111, 98, 95, 99,101,110,116, -114,101, 0, 98,103,112,105, 99, 98, 97,115,101, 0, 42, 98,103,112,105, 99, 0,111, 98, 95, 99,101,110,116,114,101, 95, 98,111, -110,101, 91, 54, 52, 93, 0,100,114, 97,119,116,121,112,101, 0,111, 98, 95, 99,101,110,116,114,101, 95, 99,117,114,115,111,114, - 0,115, 99,101,110,101,108,111, 99,107, 0, 97,114,111,117,110,100, 0,103,114,105,100, 0,110,101, 97,114, 0,102, 97,114, 0, -109,111,100,101,115,101,108,101, 99,116, 0,103,114,105,100,108,105,110,101,115, 0,103,114,105,100,115,117, 98,100,105,118, 0, -103,114,105,100,102,108, 97,103, 0,116,119,116,121,112,101, 0,116,119,109,111,100,101, 0,116,119,102,108, 97,103, 0,112, 97, -100, 50, 91, 50, 93, 0, 97,102,116,101,114,100,114, 97,119, 95,116,114, 97,110,115,112, 0, 97,102,116,101,114,100,114, 97,119, - 95,120,114, 97,121, 0, 97,102,116,101,114,100,114, 97,119, 95,120,114, 97,121,116,114, 97,110,115,112, 0,122, 98,117,102, 0, -120,114, 97,121, 0,112, 97,100, 51, 91, 50, 93, 0, 42,112,114,111,112,101,114,116,105,101,115, 95,115,116,111,114, 97,103,101, - 0,118,101,114,116, 0,104,111,114, 0,109, 97,115,107, 0,109,105,110, 91, 50, 93, 0,109, 97,120, 91, 50, 93, 0,109,105,110, -122,111,111,109, 0,109, 97,120,122,111,111,109, 0,115, 99,114,111,108,108, 0,115, 99,114,111,108,108, 95,117,105, 0,107,101, -101,112,116,111,116, 0,107,101,101,112,122,111,111,109, 0,107,101,101,112,111,102,115, 0, 97,108,105,103,110, 0,119,105,110, -120, 0,119,105,110,121, 0,111,108,100,119,105,110,120, 0,111,108,100,119,105,110,121, 0, 42,116, 97, 98, 95,111,102,102,115, -101,116, 0,116, 97, 98, 95,110,117,109, 0,116, 97, 98, 95, 99,117,114, 0,114,112,116, 95,109, 97,115,107, 0,118, 50,100, 0, - 42, 97,100,115, 0,103,104,111,115,116, 67,117,114,118,101,115, 0, 97,117,116,111,115,110, 97,112, 0, 99,117,114,115,111,114, - 86, 97,108, 0,109, 97,105,110, 98, 0,109, 97,105,110, 98,111, 0,109, 97,105,110, 98,117,115,101,114, 0,114,101, 95, 97,108, -105,103,110, 0,112,114,101,118,105,101,119, 0,116,101,120,116,117,114,101, 95, 99,111,110,116,101,120,116, 0,112, 97,116,104, -102,108, 97,103, 0,100, 97,116, 97,105, 99,111,110, 0, 42,112,105,110,105,100, 0, 42,116,101,120,117,115,101,114, 0,114,101, -110,100,101,114, 95,115,105,122,101, 0, 99,104, 97,110,115,104,111,119,110, 0,122,101, 98,114, 97, 0,122,111,111,109, 0,116, -105,116,108,101, 91, 51, 50, 93, 0,100,105,114, 91, 49, 48, 53, 54, 93, 0,102,105,108,101, 91, 50, 53, 54, 93, 0,114,101,110, - 97,109,101,102,105,108,101, 91, 50, 53, 54, 93, 0,114,101,110, 97,109,101,101,100,105,116, 91, 50, 53, 54, 93, 0,102,105,108, -116,101,114, 95,103,108,111, 98, 91, 54, 52, 93, 0, 97, 99,116,105,118,101, 95,102,105,108,101, 0,115,101,108, 95,102,105,114, -115,116, 0,115,101,108, 95,108, 97,115,116, 0,115,111,114,116, 0,100,105,115,112,108, 97,121, 0,102, 95,102,112, 0,102,112, - 95,115,116,114, 91, 56, 93, 0,115, 99,114,111,108,108, 95,111,102,102,115,101,116, 0, 42,112, 97,114, 97,109,115, 0, 42,102, -105,108,101,115, 0, 42,102,111,108,100,101,114,115, 95,112,114,101,118, 0, 42,102,111,108,100,101,114,115, 95,110,101,120,116, - 0, 42,111,112, 0, 42,115,109,111,111,116,104,115, 99,114,111,108,108, 95,116,105,109,101,114, 0, 42,108, 97,121,111,117,116, - 0,114,101, 99,101,110,116,110,114, 0, 98,111,111,107,109, 97,114,107,110,114, 0,115,121,115,116,101,109,110,114, 0,116,114, -101,101, 0, 42,116,114,101,101,115,116,111,114,101, 0,115,101, 97,114, 99,104, 95,115,116,114,105,110,103, 91, 51, 50, 93, 0, -115,101, 97,114, 99,104, 95,116,115,101, 0,111,117,116,108,105,110,101,118,105,115, 0,115,116,111,114,101,102,108, 97,103, 0, -115,101, 97,114, 99,104, 95,102,108, 97,103,115, 0, 42, 99,117,109, 97,112, 0,115, 99,111,112,101,115, 0,115, 97,109,112,108, -101, 95,108,105,110,101, 95,104,105,115,116, 0, 99,117,114,115,111,114, 91, 50, 93, 0, 99,101,110,116,120, 0, 99,101,110,116, -121, 0, 99,117,114,116,105,108,101, 0,108,111, 99,107, 0,112,105,110, 0,100,116, 95,117,118, 0,115,116,105, 99,107,121, 0, -100,116, 95,117,118,115,116,114,101,116, 99,104, 0, 42,116,101,120,116, 0,116,111,112, 0,118,105,101,119,108,105,110,101,115, - 0,109,101,110,117,110,114, 0,108,104,101,105,103,104,116, 0, 99,119,105,100,116,104, 0,108,105,110,101,110,114,115, 95,116, -111,116, 0,108,101,102,116, 0,115,104,111,119,108,105,110,101,110,114,115, 0,116, 97, 98,110,117,109, 98,101,114, 0,115,104, -111,119,115,121,110,116, 97,120, 0,108,105,110,101, 95,104,108,105,103,104,116, 0,111,118,101,114,119,114,105,116,101, 0,108, -105,118,101, 95,101,100,105,116, 0,112,105,120, 95,112,101,114, 95,108,105,110,101, 0,116,120,116,115, 99,114,111,108,108, 0, -116,120,116, 98, 97,114, 0,119,111,114,100,119,114, 97,112, 0,100,111,112,108,117,103,105,110,115, 0,102,105,110,100,115,116, -114, 91, 50, 53, 54, 93, 0,114,101,112,108, 97, 99,101,115,116,114, 91, 50, 53, 54, 93, 0,109, 97,114,103,105,110, 95, 99,111, -108,117,109,110, 0, 42,100,114, 97,119, 99, 97, 99,104,101, 0, 42,112,121, 95,100,114, 97,119, 0, 42,112,121, 95,101,118,101, -110,116, 0, 42,112,121, 95, 98,117,116,116,111,110, 0, 42,112,121, 95, 98,114,111,119,115,101,114, 99, 97,108,108, 98, 97, 99, -107, 0, 42,112,121, 95,103,108,111, 98, 97,108,100,105, 99,116, 0,108, 97,115,116,115,112, 97, 99,101, 0,115, 99,114,105,112, -116,110, 97,109,101, 91, 49, 48, 50, 52, 93, 0,115, 99,114,105,112,116, 97,114,103, 91, 50, 53, 54, 93, 0, 42,115, 99,114,105, -112,116, 0, 42, 98,117,116, 95,114,101,102,115, 0, 42, 97,114,114, 97,121, 0, 99, 97, 99,104,101,115, 0, 99, 97, 99,104,101, - 95,100,105,115,112,108, 97,121, 0, 42,105,100, 0, 97,115,112,101, 99,116, 0,112, 97,100,102, 0,109,120, 0,109,121, 0, 42, -101,100,105,116,116,114,101,101, 0,116,114,101,101,116,121,112,101, 0,116,101,120,102,114,111,109, 0,115,104, 97,100,101,114, -102,114,111,109, 0,108,105,110,107,100,114, 97,103, 0,108,101,110, 95, 97,108,108,111, 99, 0, 99,117,114,115,111,114, 0,115, - 99,114,111,108,108, 98, 97, 99,107, 0,104,105,115,116,111,114,121, 0,112,114,111,109,112,116, 91, 50, 53, 54, 93, 0,108, 97, -110,103,117, 97,103,101, 91, 51, 50, 93, 0,115,101,108, 95,115,116, 97,114,116, 0,115,101,108, 95,101,110,100, 0,102,105,108, -116,101,114, 91, 54, 52, 93, 0,120,108,111, 99,107,111,102, 0,121,108,111, 99,107,111,102, 0,117,115,101,114, 0,112, 97,116, -104, 95,108,101,110,103,116,104, 0,108,111, 99, 91, 50, 93, 0,115,116, 97, 98,109, 97,116, 91, 52, 93, 91, 52, 93, 0,117,110, -105,115,116, 97, 98,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,116,112,114,111, 99, 95,102,108, 97,103, 0,114,117,110, -116,105,109,101, 95,102,108, 97,103, 0,102,105,108,101,110, 97,109,101, 91, 49, 48, 50, 52, 93, 0, 98,108,102, 95,105,100, 0, -117,105,102,111,110,116, 95,105,100, 0,114, 95,116,111, 95,108, 0,112,111,105,110,116,115, 0,107,101,114,110,105,110,103, 0, -105,116, 97,108,105, 99, 0, 98,111,108,100, 0,115,104, 97,100,111,119, 0,115,104, 97,100,120, 0,115,104, 97,100,121, 0,115, -104, 97,100,111,119, 97,108,112,104, 97, 0,115,104, 97,100,111,119, 99,111,108,111,114, 0,112, 97,110,101,108,116,105,116,108, -101, 0,103,114,111,117,112,108, 97, 98,101,108, 0,119,105,100,103,101,116,108, 97, 98,101,108, 0,119,105,100,103,101,116, 0, -112, 97,110,101,108,122,111,111,109, 0,109,105,110,108, 97, 98,101,108, 99,104, 97,114,115, 0,109,105,110,119,105,100,103,101, -116, 99,104, 97,114,115, 0, 99,111,108,117,109,110,115,112, 97, 99,101, 0,116,101,109,112,108, 97,116,101,115,112, 97, 99,101, - 0, 98,111,120,115,112, 97, 99,101, 0, 98,117,116,116,111,110,115,112, 97, 99,101,120, 0, 98,117,116,116,111,110,115,112, 97, - 99,101,121, 0,112, 97,110,101,108,115,112, 97, 99,101, 0,112, 97,110,101,108,111,117,116,101,114, 0,111,117,116,108,105,110, -101, 91, 52, 93, 0,105,110,110,101,114, 91, 52, 93, 0,105,110,110,101,114, 95,115,101,108, 91, 52, 93, 0,105,116,101,109, 91, - 52, 93, 0,116,101,120,116, 91, 52, 93, 0,116,101,120,116, 95,115,101,108, 91, 52, 93, 0,115,104, 97,100,101,100, 0,115,104, - 97,100,101,116,111,112, 0,115,104, 97,100,101,100,111,119,110, 0, 97,108,112,104, 97, 95, 99,104,101, 99,107, 0,105,110,110, -101,114, 95, 97,110,105,109, 91, 52, 93, 0,105,110,110,101,114, 95, 97,110,105,109, 95,115,101,108, 91, 52, 93, 0,105,110,110, -101,114, 95,107,101,121, 91, 52, 93, 0,105,110,110,101,114, 95,107,101,121, 95,115,101,108, 91, 52, 93, 0,105,110,110,101,114, - 95,100,114,105,118,101,110, 91, 52, 93, 0,105,110,110,101,114, 95,100,114,105,118,101,110, 95,115,101,108, 91, 52, 93, 0,104, -101, 97,100,101,114, 91, 52, 93, 0,115,104,111,119, 95,104,101, 97,100,101,114, 0,119, 99,111,108, 95,114,101,103,117,108, 97, -114, 0,119, 99,111,108, 95,116,111,111,108, 0,119, 99,111,108, 95,116,101,120,116, 0,119, 99,111,108, 95,114, 97,100,105,111, - 0,119, 99,111,108, 95,111,112,116,105,111,110, 0,119, 99,111,108, 95,116,111,103,103,108,101, 0,119, 99,111,108, 95,110,117, -109, 0,119, 99,111,108, 95,110,117,109,115,108,105,100,101,114, 0,119, 99,111,108, 95,109,101,110,117, 0,119, 99,111,108, 95, -112,117,108,108,100,111,119,110, 0,119, 99,111,108, 95,109,101,110,117, 95, 98, 97, 99,107, 0,119, 99,111,108, 95,109,101,110, -117, 95,105,116,101,109, 0,119, 99,111,108, 95,116,111,111,108,116,105,112, 0,119, 99,111,108, 95, 98,111,120, 0,119, 99,111, -108, 95,115, 99,114,111,108,108, 0,119, 99,111,108, 95,112,114,111,103,114,101,115,115, 0,119, 99,111,108, 95,108,105,115,116, - 95,105,116,101,109, 0,119, 99,111,108, 95,115,116, 97,116,101, 0,112, 97,110,101,108, 0,105, 99,111,110,102,105,108,101, 91, - 50, 53, 54, 93, 0,105, 99,111,110, 95, 97,108,112,104, 97, 0, 98, 97, 99,107, 91, 52, 93, 0,116,105,116,108,101, 91, 52, 93, - 0,116,101,120,116, 95,104,105, 91, 52, 93, 0,104,101, 97,100,101,114, 95,116,105,116,108,101, 91, 52, 93, 0,104,101, 97,100, -101,114, 95,116,101,120,116, 91, 52, 93, 0,104,101, 97,100,101,114, 95,116,101,120,116, 95,104,105, 91, 52, 93, 0, 98,117,116, -116,111,110, 91, 52, 93, 0, 98,117,116,116,111,110, 95,116,105,116,108,101, 91, 52, 93, 0, 98,117,116,116,111,110, 95,116,101, -120,116, 91, 52, 93, 0, 98,117,116,116,111,110, 95,116,101,120,116, 95,104,105, 91, 52, 93, 0,108,105,115,116, 91, 52, 93, 0, -108,105,115,116, 95,116,105,116,108,101, 91, 52, 93, 0,108,105,115,116, 95,116,101,120,116, 91, 52, 93, 0,108,105,115,116, 95, -116,101,120,116, 95,104,105, 91, 52, 93, 0,112, 97,110,101,108, 91, 52, 93, 0,112, 97,110,101,108, 95,116,105,116,108,101, 91, - 52, 93, 0,112, 97,110,101,108, 95,116,101,120,116, 91, 52, 93, 0,112, 97,110,101,108, 95,116,101,120,116, 95,104,105, 91, 52, - 93, 0,115,104, 97,100,101, 49, 91, 52, 93, 0,115,104, 97,100,101, 50, 91, 52, 93, 0,104,105,108,105,116,101, 91, 52, 93, 0, -103,114,105,100, 91, 52, 93, 0,119,105,114,101, 91, 52, 93, 0,115,101,108,101, 99,116, 91, 52, 93, 0,108, 97,109,112, 91, 52, - 93, 0,115,112,101, 97,107,101,114, 91, 52, 93, 0,101,109,112,116,121, 91, 52, 93, 0, 99, 97,109,101,114, 97, 91, 52, 93, 0, -112, 97,100, 91, 56, 93, 0, 97, 99,116,105,118,101, 91, 52, 93, 0,103,114,111,117,112, 91, 52, 93, 0,103,114,111,117,112, 95, - 97, 99,116,105,118,101, 91, 52, 93, 0,116,114, 97,110,115,102,111,114,109, 91, 52, 93, 0,118,101,114,116,101,120, 91, 52, 93, - 0,118,101,114,116,101,120, 95,115,101,108,101, 99,116, 91, 52, 93, 0,101,100,103,101, 91, 52, 93, 0,101,100,103,101, 95,115, -101,108,101, 99,116, 91, 52, 93, 0,101,100,103,101, 95,115,101, 97,109, 91, 52, 93, 0,101,100,103,101, 95,115,104, 97,114,112, - 91, 52, 93, 0,101,100,103,101, 95,102, 97, 99,101,115,101,108, 91, 52, 93, 0,101,100,103,101, 95, 99,114,101, 97,115,101, 91, - 52, 93, 0,102, 97, 99,101, 91, 52, 93, 0,102, 97, 99,101, 95,115,101,108,101, 99,116, 91, 52, 93, 0,102, 97, 99,101, 95,100, -111,116, 91, 52, 93, 0,101,120,116,114, 97, 95,101,100,103,101, 95,108,101,110, 91, 52, 93, 0,101,120,116,114, 97, 95,102, 97, - 99,101, 95, 97,110,103,108,101, 91, 52, 93, 0,101,120,116,114, 97, 95,102, 97, 99,101, 95, 97,114,101, 97, 91, 52, 93, 0,112, - 97,100, 51, 91, 52, 93, 0,110,111,114,109, 97,108, 91, 52, 93, 0,118,101,114,116,101,120, 95,110,111,114,109, 97,108, 91, 52, - 93, 0, 98,111,110,101, 95,115,111,108,105,100, 91, 52, 93, 0, 98,111,110,101, 95,112,111,115,101, 91, 52, 93, 0,115,116,114, -105,112, 91, 52, 93, 0,115,116,114,105,112, 95,115,101,108,101, 99,116, 91, 52, 93, 0, 99,102,114, 97,109,101, 91, 52, 93, 0, -110,117,114, 98, 95,117,108,105,110,101, 91, 52, 93, 0,110,117,114, 98, 95,118,108,105,110,101, 91, 52, 93, 0, 97, 99,116, 95, -115,112,108,105,110,101, 91, 52, 93, 0,110,117,114, 98, 95,115,101,108, 95,117,108,105,110,101, 91, 52, 93, 0,110,117,114, 98, - 95,115,101,108, 95,118,108,105,110,101, 91, 52, 93, 0,108, 97,115,116,115,101,108, 95,112,111,105,110,116, 91, 52, 93, 0,104, - 97,110,100,108,101, 95,102,114,101,101, 91, 52, 93, 0,104, 97,110,100,108,101, 95, 97,117,116,111, 91, 52, 93, 0,104, 97,110, -100,108,101, 95,118,101, 99,116, 91, 52, 93, 0,104, 97,110,100,108,101, 95, 97,108,105,103,110, 91, 52, 93, 0,104, 97,110,100, -108,101, 95, 97,117,116,111, 95, 99,108, 97,109,112,101,100, 91, 52, 93, 0,104, 97,110,100,108,101, 95,115,101,108, 95,102,114, -101,101, 91, 52, 93, 0,104, 97,110,100,108,101, 95,115,101,108, 95, 97,117,116,111, 91, 52, 93, 0,104, 97,110,100,108,101, 95, -115,101,108, 95,118,101, 99,116, 91, 52, 93, 0,104, 97,110,100,108,101, 95,115,101,108, 95, 97,108,105,103,110, 91, 52, 93, 0, -104, 97,110,100,108,101, 95,115,101,108, 95, 97,117,116,111, 95, 99,108, 97,109,112,101,100, 91, 52, 93, 0,100,115, 95, 99,104, - 97,110,110,101,108, 91, 52, 93, 0,100,115, 95,115,117, 98, 99,104, 97,110,110,101,108, 91, 52, 93, 0, 99,111,110,115,111,108, -101, 95,111,117,116,112,117,116, 91, 52, 93, 0, 99,111,110,115,111,108,101, 95,105,110,112,117,116, 91, 52, 93, 0, 99,111,110, -115,111,108,101, 95,105,110,102,111, 91, 52, 93, 0, 99,111,110,115,111,108,101, 95,101,114,114,111,114, 91, 52, 93, 0, 99,111, -110,115,111,108,101, 95, 99,117,114,115,111,114, 91, 52, 93, 0,118,101,114,116,101,120, 95,115,105,122,101, 0,111,117,116,108, -105,110,101, 95,119,105,100,116,104, 0,102, 97, 99,101,100,111,116, 95,115,105,122,101, 0,110,111,111,100,108,101, 95, 99,117, -114,118,105,110,103, 0,115,121,110,116, 97,120,108, 91, 52, 93, 0,115,121,110,116, 97,120,110, 91, 52, 93, 0,115,121,110,116, - 97,120, 98, 91, 52, 93, 0,115,121,110,116, 97,120,118, 91, 52, 93, 0,115,121,110,116, 97,120, 99, 91, 52, 93, 0,109,111,118, -105,101, 91, 52, 93, 0,109,111,118,105,101, 99,108,105,112, 91, 52, 93, 0,105,109, 97,103,101, 91, 52, 93, 0,115, 99,101,110, -101, 91, 52, 93, 0, 97,117,100,105,111, 91, 52, 93, 0,101,102,102,101, 99,116, 91, 52, 93, 0,112,108,117,103,105,110, 91, 52, - 93, 0,116,114, 97,110,115,105,116,105,111,110, 91, 52, 93, 0,109,101,116, 97, 91, 52, 93, 0,101,100,105,116,109,101,115,104, - 95, 97, 99,116,105,118,101, 91, 52, 93, 0,104, 97,110,100,108,101, 95,118,101,114,116,101,120, 91, 52, 93, 0,104, 97,110,100, -108,101, 95,118,101,114,116,101,120, 95,115,101,108,101, 99,116, 91, 52, 93, 0,104, 97,110,100,108,101, 95,118,101,114,116,101, -120, 95,115,105,122,101, 0,109, 97,114,107,101,114, 95,111,117,116,108,105,110,101, 91, 52, 93, 0,109, 97,114,107,101,114, 91, - 52, 93, 0, 97, 99,116, 95,109, 97,114,107,101,114, 91, 52, 93, 0,115,101,108, 95,109, 97,114,107,101,114, 91, 52, 93, 0,100, -105,115, 95,109, 97,114,107,101,114, 91, 52, 93, 0,108,111, 99,107, 95,109, 97,114,107,101,114, 91, 52, 93, 0, 98,117,110,100, -108,101, 95,115,111,108,105,100, 91, 52, 93, 0,112, 97,116,104, 95, 98,101,102,111,114,101, 91, 52, 93, 0,112, 97,116,104, 95, - 97,102,116,101,114, 91, 52, 93, 0, 99, 97,109,101,114, 97, 95,112, 97,116,104, 91, 52, 93, 0,104,112, 97,100, 91, 55, 93, 0, -112,114,101,118,105,101,119, 95, 98, 97, 99,107, 91, 52, 93, 0,112,114,101,118,105,101,119, 95,115,116,105,116, 99,104, 95,102, - 97, 99,101, 91, 52, 93, 0,112,114,101,118,105,101,119, 95,115,116,105,116, 99,104, 95,101,100,103,101, 91, 52, 93, 0,112,114, -101,118,105,101,119, 95,115,116,105,116, 99,104, 95,118,101,114,116, 91, 52, 93, 0,112,114,101,118,105,101,119, 95,115,116,105, -116, 99,104, 95,115,116,105,116, 99,104, 97, 98,108,101, 91, 52, 93, 0,112,114,101,118,105,101,119, 95,115,116,105,116, 99,104, - 95,117,110,115,116,105,116, 99,104, 97, 98,108,101, 91, 52, 93, 0,112,114,101,118,105,101,119, 95,115,116,105,116, 99,104, 95, - 97, 99,116,105,118,101, 91, 52, 93, 0,109, 97,116, 99,104, 91, 52, 93, 0,115,101,108,101, 99,116,101,100, 95,104,105,103,104, -108,105,103,104,116, 91, 52, 93, 0,115,111,108,105,100, 91, 52, 93, 0,116,117,105, 0,116, 98,117,116,115, 0,116,118, 51,100, - 0,116,102,105,108,101, 0,116,105,112,111, 0,116,105,110,102,111, 0,116, 97, 99,116, 0,116,110,108, 97, 0,116,115,101,113, - 0,116,105,109, 97, 0,116,101,120,116, 0,116,111,111,112,115, 0,116,116,105,109,101, 0,116,110,111,100,101, 0,116,108,111, -103,105, 99, 0,116,117,115,101,114,112,114,101,102, 0,116, 99,111,110,115,111,108,101, 0,116, 99,108,105,112, 0,116, 97,114, -109, 91, 50, 48, 93, 0, 97, 99,116,105,118,101, 95,116,104,101,109,101, 95, 97,114,101, 97, 0,109,111,100,117,108,101, 91, 54, - 52, 93, 0,115,112,101, 99, 91, 52, 93, 0,100,117,112,102,108, 97,103, 0,115, 97,118,101,116,105,109,101, 0,116,101,109,112, -100,105,114, 91, 55, 54, 56, 93, 0,102,111,110,116,100,105,114, 91, 55, 54, 56, 93, 0,114,101,110,100,101,114,100,105,114, 91, - 49, 48, 50, 52, 93, 0,116,101,120,116,117,100,105,114, 91, 55, 54, 56, 93, 0,112,108,117,103,116,101,120,100,105,114, 91, 55, - 54, 56, 93, 0,112,108,117,103,115,101,113,100,105,114, 91, 55, 54, 56, 93, 0,112,121,116,104,111,110,100,105,114, 91, 55, 54, - 56, 93, 0,115,111,117,110,100,100,105,114, 91, 55, 54, 56, 93, 0,105,109, 97,103,101, 95,101,100,105,116,111,114, 91, 49, 48, - 50, 52, 93, 0, 97,110,105,109, 95,112,108, 97,121,101,114, 91, 49, 48, 50, 52, 93, 0, 97,110,105,109, 95,112,108, 97,121,101, -114, 95,112,114,101,115,101,116, 0,118, 50,100, 95,109,105,110, 95,103,114,105,100,115,105,122,101, 0,116,105,109,101, 99,111, -100,101, 95,115,116,121,108,101, 0,118,101,114,115,105,111,110,115, 0,100, 98,108, 95, 99,108,105, 99,107, 95,116,105,109,101, - 0,103, 97,109,101,102,108, 97,103,115, 0,119,104,101,101,108,108,105,110,101,115, 99,114,111,108,108, 0,117,105,102,108, 97, -103, 0,108, 97,110,103,117, 97,103,101, 0,117,115,101,114,112,114,101,102, 0,118,105,101,119,122,111,111,109, 0,109,105,120, - 98,117,102,115,105,122,101, 0, 97,117,100,105,111,100,101,118,105, 99,101, 0, 97,117,100,105,111,114, 97,116,101, 0, 97,117, -100,105,111,102,111,114,109, 97,116, 0, 97,117,100,105,111, 99,104, 97,110,110,101,108,115, 0,100,112,105, 0,101,110, 99,111, -100,105,110,103, 0,116,114, 97,110,115,111,112,116,115, 0,109,101,110,117,116,104,114,101,115,104,111,108,100, 49, 0,109,101, -110,117,116,104,114,101,115,104,111,108,100, 50, 0,116,104,101,109,101,115, 0,117,105,102,111,110,116,115, 0,117,105,115,116, -121,108,101,115, 0,107,101,121,109, 97,112,115, 0,117,115,101,114, 95,107,101,121,109, 97,112,115, 0, 97,100,100,111,110,115, - 0,107,101,121, 99,111,110,102,105,103,115,116,114, 91, 54, 52, 93, 0,117,110,100,111,115,116,101,112,115, 0,117,110,100,111, -109,101,109,111,114,121, 0,103,112, 95,109, 97,110,104, 97,116,116,101,110,100,105,115,116, 0,103,112, 95,101,117, 99,108,105, -100,101, 97,110,100,105,115,116, 0,103,112, 95,101,114, 97,115,101,114, 0,103,112, 95,115,101,116,116,105,110,103,115, 0,116, - 98, 95,108,101,102,116,109,111,117,115,101, 0,116, 98, 95,114,105,103,104,116,109,111,117,115,101, 0,108,105,103,104,116, 91, - 51, 93, 0,116,119, 95,104,111,116,115,112,111,116, 0,116,119, 95,102,108, 97,103, 0,116,119, 95,104, 97,110,100,108,101,115, -105,122,101, 0,116,119, 95,115,105,122,101, 0,116,101,120,116,105,109,101,111,117,116, 0,116,101,120, 99,111,108,108,101, 99, -116,114, 97,116,101, 0,119,109,100,114, 97,119,109,101,116,104,111,100, 0,100,114, 97,103,116,104,114,101,115,104,111,108,100, - 0,109,101,109, 99, 97, 99,104,101,108,105,109,105,116, 0,112,114,101,102,101,116, 99,104,102,114, 97,109,101,115, 0,102,114, - 97,109,101,115,101,114,118,101,114,112,111,114,116, 0,112, 97,100, 95,114,111,116, 95, 97,110,103,108,101, 0,111, 98, 99,101, -110,116,101,114, 95,100,105, 97, 0,114,118,105,115,105,122,101, 0,114,118,105, 98,114,105,103,104,116, 0,114,101, 99,101,110, -116, 95,102,105,108,101,115, 0,115,109,111,111,116,104, 95,118,105,101,119,116,120, 0,103,108,114,101,115,108,105,109,105,116, - 0, 99,117,114,115,115,105,122,101, 0, 99,111,108,111,114, 95,112,105, 99,107,101,114, 95,116,121,112,101, 0,105,112,111, 95, -110,101,119, 0,107,101,121,104, 97,110,100,108,101,115, 95,110,101,119, 0,115, 99,114, 99, 97,115,116,102,112,115, 0,115, 99, -114, 99, 97,115,116,119, 97,105,116, 0,119,105,100,103,101,116, 95,117,110,105,116, 0, 97,110,105,115,111,116,114,111,112,105, - 99, 95,102,105,108,116,101,114, 0,117,115,101, 95, 49, 54, 98,105,116, 95,116,101,120,116,117,114,101,115, 0,112, 97,100, 56, - 0,110,100,111,102, 95,115,101,110,115,105,116,105,118,105,116,121, 0,110,100,111,102, 95,102,108, 97,103, 0,103,108, 97,108, -112,104, 97, 99,108,105,112, 0,116,101,120,116, 95,114,101,110,100,101,114, 0,112, 97,100, 57, 0, 99,111, 98, 97, 95,119,101, -105,103,104,116, 0,115, 99,117,108,112,116, 95,112, 97,105,110,116, 95,111,118,101,114,108, 97,121, 95, 99,111,108, 91, 51, 93, - 0,116,119,101, 97,107, 95,116,104,114,101,115,104,111,108,100, 0, 97,117,116,104,111,114, 91, 56, 48, 93, 0, 99,111,109,112, -117,116,101, 95,100,101,118,105, 99,101, 95,116,121,112,101, 0, 99,111,109,112,117,116,101, 95,100,101,118,105, 99,101, 95,105, -100, 0,102, 99,117, 95,105,110, 97, 99,116,105,118,101, 95, 97,108,112,104, 97, 0,118,101,114,116, 98, 97,115,101, 0,101,100, -103,101, 98, 97,115,101, 0, 97,114,101, 97, 98, 97,115,101, 0, 42,110,101,119,115, 99,101,110,101, 0,114,101,100,114, 97,119, -115, 95,102,108, 97,103, 0,102,117,108,108, 0,116,101,109,112, 0,119,105,110,105,100, 0,100,111, 95,100,114, 97,119, 0,100, -111, 95,114,101,102,114,101,115,104, 0,100,111, 95,100,114, 97,119, 95,103,101,115,116,117,114,101, 0,100,111, 95,100,114, 97, -119, 95,112, 97,105,110,116, 99,117,114,115,111,114, 0,100,111, 95,100,114, 97,119, 95,100,114, 97,103, 0,115,119, 97,112, 0, -109, 97,105,110,119,105,110, 0,115,117, 98,119,105,110, 97, 99,116,105,118,101, 0, 42, 97,110,105,109,116,105,109,101,114, 0, - 42, 99,111,110,116,101,120,116, 0,104, 97,110,100,108,101,114, 91, 56, 93, 0, 42,110,101,119,118, 0,118,101, 99, 0, 42,118, - 49, 0, 42,118, 50, 0, 42,116,121,112,101, 0,112, 97,110,101,108,110, 97,109,101, 91, 54, 52, 93, 0,116, 97, 98,110, 97,109, -101, 91, 54, 52, 93, 0,100,114, 97,119,110, 97,109,101, 91, 54, 52, 93, 0,111,102,115,120, 0,111,102,115,121, 0,115,105,122, -101,120, 0,115,105,122,101,121, 0,108, 97, 98,101,108,111,102,115, 0, 99,111,110,116,114,111,108, 0,115,110, 97,112, 0,115, -111,114,116,111,114,100,101,114, 0, 42,112, 97,110,101,108,116, 97, 98, 0, 42, 97, 99,116,105,118,101,100, 97,116, 97, 0,108, -105,115,116, 95,115, 99,114,111,108,108, 0,108,105,115,116, 95,115,105,122,101, 0,108,105,115,116, 95,108, 97,115,116, 95,108, -101,110, 0,108,105,115,116, 95,103,114,105,112, 95,115,105,122,101, 0,108,105,115,116, 95,115,101, 97,114, 99,104, 91, 54, 52, - 93, 0, 42,118, 51, 0, 42,118, 52, 0, 42,102,117,108,108, 0, 98,117,116,115,112, 97, 99,101,116,121,112,101, 0,104,101, 97, -100,101,114,116,121,112,101, 0,115,112, 97, 99,101,100, 97,116, 97, 0,104, 97,110,100,108,101,114,115, 0, 97, 99,116,105,111, -110,122,111,110,101,115, 0,119,105,110,114, 99,116, 0,100,114, 97,119,114, 99,116, 0,115,119,105,110,105,100, 0,114,101,103, -105,111,110,116,121,112,101, 0, 97,108,105,103,110,109,101,110,116, 0,100,111, 95,100,114, 97,119, 95,111,118,101,114,108, 97, -121, 0,117,105, 98,108,111, 99,107,115, 0,112, 97,110,101,108,115, 0, 42,104,101, 97,100,101,114,115,116,114, 0, 42,114,101, -103,105,111,110,100, 97,116, 97, 0,115,117, 98,118,115,116,114, 91, 52, 93, 0,115,117, 98,118,101,114,115,105,111,110, 0,112, - 97,100,115, 0,109,105,110,118,101,114,115,105,111,110, 0,109,105,110,115,117, 98,118,101,114,115,105,111,110, 0,119,105,110, -112,111,115, 0, 42, 99,117,114,115, 99,114,101,101,110, 0, 42, 99,117,114,115, 99,101,110,101, 0,102,105,108,101,102,108, 97, -103,115, 0,103,108,111, 98, 97,108,102, 0,114,101,118,105,115,105,111,110, 0,110, 97,109,101, 91, 50, 53, 54, 93, 0,111,114, -105,103, 95,119,105,100,116,104, 0,111,114,105,103, 95,104,101,105,103,104,116, 0, 98,111,116,116,111,109, 0,114,105,103,104, -116, 0,120,111,102,115, 0,121,111,102,115, 0,108,105,102,116, 91, 51, 93, 0,103, 97,109,109, 97, 91, 51, 93, 0,103, 97,105, -110, 91, 51, 93, 0,100,105,114, 91, 55, 54, 56, 93, 0,116, 99, 0, 98,117,105,108,100, 95,115,105,122,101, 95,102,108, 97,103, -115, 0, 98,117,105,108,100, 95,116, 99, 95,102,108, 97,103,115, 0,100,111,110,101, 0,115,116, 97,114,116,115,116,105,108,108, - 0,101,110,100,115,116,105,108,108, 0, 42,115,116,114,105,112,100, 97,116, 97, 0, 42, 99,114,111,112, 0, 42,116,114, 97,110, -115,102,111,114,109, 0, 42, 99,111,108,111,114, 95, 98, 97,108, 97,110, 99,101, 0, 42,105,110,115,116, 97,110, 99,101, 95,112, -114,105,118, 97,116,101, 95,100, 97,116, 97, 0, 42, 42, 99,117,114,114,101,110,116, 95,112,114,105,118, 97,116,101, 95,100, 97, -116, 97, 0, 42,116,109,112, 0,115,116, 97,114,116,111,102,115, 0,101,110,100,111,102,115, 0,109, 97, 99,104,105,110,101, 0, -115,116, 97,114,116,100,105,115,112, 0,101,110,100,100,105,115,112, 0,115, 97,116, 0,109,117,108, 0,104, 97,110,100,115,105, -122,101, 0, 97,110,105,109, 95,112,114,101,115,101,101,107, 0,115,116,114,101, 97,109,105,110,100,101,120, 0,109,117,108,116, -105, 99, 97,109, 95,115,111,117,114, 99,101, 0, 99,108,105,112, 95,102,108, 97,103, 0, 42,115,116,114,105,112, 0, 42,115, 99, -101,110,101, 95, 99, 97,109,101,114, 97, 0,101,102,102,101, 99,116, 95,102, 97,100,101,114, 0,115,112,101,101,100, 95,102, 97, -100,101,114, 0, 42,115,101,113, 49, 0, 42,115,101,113, 50, 0, 42,115,101,113, 51, 0,115,101,113, 98, 97,115,101, 0, 42,115, -111,117,110,100, 0, 42,115, 99,101,110,101, 95,115,111,117,110,100, 0,112,105,116, 99,104, 0,112, 97,110, 0,115,116,114,111, - 98,101, 0, 42,101,102,102,101, 99,116,100, 97,116, 97, 0, 97,110,105,109, 95,115,116, 97,114,116,111,102,115, 0, 97,110,105, -109, 95,101,110,100,111,102,115, 0, 98,108,101,110,100, 95,109,111,100,101, 0, 98,108,101,110,100, 95,111,112, 97, 99,105,116, -121, 0, 42,111,108,100, 98, 97,115,101,112, 0, 42,112, 97,114,115,101,113, 0, 42,115,101,113, 98, 97,115,101,112, 0,109,101, -116, 97,115,116, 97, 99,107, 0, 42, 97, 99,116, 95,115,101,113, 0, 97, 99,116, 95,105,109, 97,103,101,100,105,114, 91, 49, 48, - 50, 52, 93, 0, 97, 99,116, 95,115,111,117,110,100,100,105,114, 91, 49, 48, 50, 52, 93, 0,111,118,101,114, 95,111,102,115, 0, -111,118,101,114, 95, 99,102,114, 97, 0,111,118,101,114, 95,102,108, 97,103, 0,111,118,101,114, 95, 98,111,114,100,101,114, 0, -101,100,103,101, 87,105,100,116,104, 0,102,111,114,119, 97,114,100, 0,119,105,112,101,116,121,112,101, 0,102, 77,105,110,105, - 0,102, 67,108, 97,109,112, 0,102, 66,111,111,115,116, 0,100, 68,105,115,116, 0,100, 81,117, 97,108,105,116,121, 0, 98, 78, -111, 67,111,109,112, 0, 83, 99, 97,108,101,120, 73,110,105, 0, 83, 99, 97,108,101,121, 73,110,105, 0,120, 73,110,105, 0,121, - 73,110,105, 0,114,111,116, 73,110,105, 0,105,110,116,101,114,112,111,108, 97,116,105,111,110, 0,117,110,105,102,111,114,109, - 95,115, 99, 97,108,101, 0, 42,102,114, 97,109,101, 77, 97,112, 0,103,108,111, 98, 97,108, 83,112,101,101,100, 0,108, 97,115, -116, 86, 97,108,105,100, 70,114, 97,109,101, 0, 98,117,116,116,121,112,101, 0,117,115,101,114,106,105,116, 0,115,116, 97, 0, -116,111,116,112, 97,114,116, 0,110,111,114,109,102, 97, 99, 0,111, 98,102, 97, 99, 0,114, 97,110,100,102, 97, 99, 0,116,101, -120,102, 97, 99, 0,114, 97,110,100,108,105,102,101, 0,102,111,114, 99,101, 91, 51, 93, 0,118,101, 99,116,115,105,122,101, 0, -109, 97,120,108,101,110, 0,100,101,102,118,101, 99, 91, 51, 93, 0,109,117,108,116, 91, 52, 93, 0,108,105,102,101, 91, 52, 93, - 0, 99,104,105,108,100, 91, 52, 93, 0,109, 97,116, 91, 52, 93, 0,116,101,120,109, 97,112, 0, 99,117,114,109,117,108,116, 0, -115,116, 97,116,105, 99,115,116,101,112, 0,111,109, 97,116, 0,116,105,109,101,116,101,120, 0,115,112,101,101,100,116,101,120, - 0,102,108, 97,103, 50,110,101,103, 0,118,101,114,116,103,114,111,117,112, 95,118, 0,118,103,114,111,117,112,110, 97,109,101, - 91, 54, 52, 93, 0,118,103,114,111,117,112,110, 97,109,101, 95,118, 91, 54, 52, 93, 0, 42,107,101,121,115, 0,109,105,110,102, - 97, 99, 0,110,114, 0,117,115,101,100, 0,117,115,101,100,101,108,101,109, 0, 42,112,111,105,110, 0,114,101,115,101,116,100, -105,115,116, 0,108, 97,115,116,118, 97,108, 0, 42,109, 97, 0,107,101,121, 0,113,117, 97,108, 0,113,117, 97,108, 50, 0,116, - 97,114,103,101,116, 78, 97,109,101, 91, 54, 52, 93, 0,116,111,103,103,108,101, 78, 97,109,101, 91, 54, 52, 93, 0,118, 97,108, -117,101, 91, 54, 52, 93, 0,109, 97,120,118, 97,108,117,101, 91, 54, 52, 93, 0,100,101,108, 97,121, 0,100,117,114, 97,116,105, -111,110, 0,109, 97,116,101,114,105, 97,108, 78, 97,109,101, 91, 54, 52, 93, 0,100, 97,109,112,116,105,109,101,114, 0,112,114, -111,112,110, 97,109,101, 91, 54, 52, 93, 0,109, 97,116,110, 97,109,101, 91, 54, 52, 93, 0, 97,120,105,115,102,108, 97,103, 0, -112,111,115,101, 99,104, 97,110,110,101,108, 91, 54, 52, 93, 0, 99,111,110,115,116,114, 97,105,110,116, 91, 54, 52, 93, 0, 42, -102,114,111,109, 79, 98,106,101, 99,116, 0,115,117, 98,106,101, 99,116, 91, 54, 52, 93, 0, 98,111,100,121, 91, 54, 52, 93, 0, -111,116,121,112,101, 0,112,117,108,115,101, 0,102,114,101,113, 0,116,111,116,108,105,110,107,115, 0, 42, 42,108,105,110,107, -115, 0,116, 97,112, 0,106,111,121,105,110,100,101,120, 0, 97,120,105,115, 95,115,105,110,103,108,101, 0, 97,120,105,115,102, - 0, 98,117,116,116,111,110, 0,104, 97,116, 0,104, 97,116,102, 0,112,114,101, 99,105,115,105,111,110, 0,115,116,114, 91, 49, - 50, 56, 93, 0, 42,109,121,110,101,119, 0,105,110,112,117,116,115, 0,116,111,116,115,108,105,110,107,115, 0, 42, 42,115,108, -105,110,107,115, 0,118, 97,108,111, 0,115,116, 97,116,101, 95,109, 97,115,107, 0, 42, 97, 99,116, 0,102,114, 97,109,101, 80, -114,111,112, 91, 54, 52, 93, 0, 98,108,101,110,100,105,110, 0,112,114,105,111,114,105,116,121, 0,101,110,100, 95,114,101,115, -101,116, 0,115,116,114,105,100,101, 97,120,105,115, 0,115,116,114,105,100,101,108,101,110,103,116,104, 0,108, 97,121,101,114, - 95,119,101,105,103,104,116, 0,109,105,110, 95,103, 97,105,110, 0,109, 97,120, 95,103, 97,105,110, 0,114,101,102,101,114,101, -110, 99,101, 95,100,105,115,116, 97,110, 99,101, 0,109, 97,120, 95,100,105,115,116, 97,110, 99,101, 0,114,111,108,108,111,102, -102, 95,102, 97, 99,116,111,114, 0, 99,111,110,101, 95,105,110,110,101,114, 95, 97,110,103,108,101, 0, 99,111,110,101, 95,111, -117,116,101,114, 95, 97,110,103,108,101, 0, 99,111,110,101, 95,111,117,116,101,114, 95,103, 97,105,110, 0,115,110,100,110,114, - 0,115,111,117,110,100, 51, 68, 0,112, 97,100, 54, 91, 49, 93, 0, 42,109,101, 0,108,105,110, 86,101,108,111, 99,105,116,121, - 91, 51, 93, 0, 97,110,103, 86,101,108,111, 99,105,116,121, 91, 51, 93, 0,108,111, 99, 97,108,102,108, 97,103, 0,100,121,110, - 95,111,112,101,114, 97,116,105,111,110, 0,102,111,114, 99,101,108,111, 99, 91, 51, 93, 0,102,111,114, 99,101,114,111,116, 91, - 51, 93, 0,112, 97,100, 49, 91, 51, 93, 0,108,105,110,101, 97,114,118,101,108,111, 99,105,116,121, 91, 51, 93, 0, 97,110,103, -117,108, 97,114,118,101,108,111, 99,105,116,121, 91, 51, 93, 0, 42,114,101,102,101,114,101,110, 99,101, 0,109,105,110, 0,109, - 97,120, 0,114,111,116,100, 97,109,112, 0,109,105,110,108,111, 99, 91, 51, 93, 0,109, 97,120,108,111, 99, 91, 51, 93, 0,109, -105,110,114,111,116, 91, 51, 93, 0,109, 97,120,114,111,116, 91, 51, 93, 0,109, 97,116,112,114,111,112, 91, 54, 52, 93, 0, 98, -117,116,115,116, 97, 0, 98,117,116,101,110,100, 0,100,105,115,116,114,105, 98,117,116,105,111,110, 0,105,110,116, 95, 97,114, -103, 95, 49, 0,105,110,116, 95, 97,114,103, 95, 50, 0,102,108,111, 97,116, 95, 97,114,103, 95, 49, 0,102,108,111, 97,116, 95, - 97,114,103, 95, 50, 0,116,111, 80,114,111,112, 78, 97,109,101, 91, 54, 52, 93, 0, 42,116,111, 79, 98,106,101, 99,116, 0, 98, -111,100,121, 84,121,112,101, 0,102,105,108,101,110, 97,109,101, 91, 54, 52, 93, 0,108,111, 97,100, 97,110,105,110, 97,109,101, - 91, 54, 52, 93, 0,105,110,116, 95, 97,114,103, 0,102,108,111, 97,116, 95, 97,114,103, 0,105,110,102,108,117,101,110, 99,101, - 0, 42,115,117, 98,116, 97,114,103,101,116, 0,102, 97, 99,105,110,103, 97,120,105,115, 0,118,101,108,111, 99,105,116,121, 0, - 97, 99, 99,101,108,101,114, 97,116,105,111,110, 0,116,117,114,110,115,112,101,101,100, 0,117,112,100, 97,116,101, 84,105,109, -101, 0, 42,110, 97,118,109,101,115,104, 0,103,111, 0, 42,110,101,119,112, 97, 99,107,101,100,102,105,108,101, 0, 97,116,116, -101,110,117, 97,116,105,111,110, 0,100,105,115,116, 97,110, 99,101, 0, 42, 99, 97, 99,104,101, 0, 42,119, 97,118,101,102,111, -114,109, 0, 42,112,108, 97,121, 98, 97, 99,107, 95,104, 97,110,100,108,101, 0, 42,108, 97,109,112,114,101,110, 0,103,111, 98, -106,101, 99,116, 0,100,117,112,108,105, 95,111,102,115, 91, 51, 93, 0, 42,112,114,111,112, 0, 99,104,105,108,100, 98, 97,115, -101, 0,114,111,108,108, 0,104,101, 97,100, 91, 51, 93, 0,116, 97,105,108, 91, 51, 93, 0, 98,111,110,101, 95,109, 97,116, 91, - 51, 93, 91, 51, 93, 0, 97,114,109, 95,104,101, 97,100, 91, 51, 93, 0, 97,114,109, 95,116, 97,105,108, 91, 51, 93, 0, 97,114, -109, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 97,114,109, 95,114,111,108,108, 0,120,119,105,100,116,104, 0,122,119,105,100, -116,104, 0,101, 97,115,101, 49, 0,101, 97,115,101, 50, 0,114, 97,100, 95,104,101, 97,100, 0,114, 97,100, 95,116, 97,105,108, - 0,112, 97,100, 91, 49, 93, 0, 98,111,110,101, 98, 97,115,101, 0, 99,104, 97,105,110, 98, 97,115,101, 0, 42,101,100, 98,111, - 0, 42, 97, 99,116, 95, 98,111,110,101, 0, 42, 97, 99,116, 95,101,100, 98,111,110,101, 0, 42,115,107,101,116, 99,104, 0,103, -101,118,101,114,116,100,101,102,111,114,109,101,114, 0,108, 97,121,101,114, 95,117,115,101,100, 0,108, 97,121,101,114, 95,112, -114,111,116,101, 99,116,101,100, 0,103,104,111,115,116,101,112, 0,103,104,111,115,116,115,105,122,101, 0,103,104,111,115,116, -116,121,112,101, 0,112, 97,116,104,115,105,122,101, 0,103,104,111,115,116,115,102, 0,103,104,111,115,116,101,102, 0,112, 97, -116,104,115,102, 0,112, 97,116,104,101,102, 0,112, 97,116,104, 98, 99, 0,112, 97,116,104, 97, 99, 0, 42,112,111,105,110,116, -115, 0,115,116, 97,114,116, 95,102,114, 97,109,101, 0,101,110,100, 95,102,114, 97,109,101, 0,103,104,111,115,116, 95,115,102, - 0,103,104,111,115,116, 95,101,102, 0,103,104,111,115,116, 95, 98, 99, 0,103,104,111,115,116, 95, 97, 99, 0,103,104,111,115, -116, 95,116,121,112,101, 0,103,104,111,115,116, 95,115,116,101,112, 0,103,104,111,115,116, 95,102,108, 97,103, 0,112, 97,116, -104, 95,116,121,112,101, 0,112, 97,116,104, 95,115,116,101,112, 0,112, 97,116,104, 95,118,105,101,119,102,108, 97,103, 0,112, - 97,116,104, 95, 98, 97,107,101,102,108, 97,103, 0,112, 97,116,104, 95,115,102, 0,112, 97,116,104, 95,101,102, 0,112, 97,116, -104, 95, 98, 99, 0,112, 97,116,104, 95, 97, 99, 0,105,107,102,108, 97,103, 0, 97,103,114,112, 95,105,110,100,101,120, 0, 99, -111,110,115,116,102,108, 97,103, 0,115,101,108,101, 99,116,102,108, 97,103, 0,112, 97,100, 48, 91, 54, 93, 0, 42, 98,111,110, -101, 0, 42, 99,104,105,108,100, 0,105,107,116,114,101,101, 0,115,105,107,116,114,101,101, 0, 42, 99,117,115,116,111,109, 0, - 42, 99,117,115,116,111,109, 95,116,120, 0,101,117,108, 91, 51, 93, 0, 99,104, 97,110, 95,109, 97,116, 91, 52, 93, 91, 52, 93, - 0,112,111,115,101, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,101, 95,104,101, 97,100, 91, 51, 93, 0,112,111,115, -101, 95,116, 97,105,108, 91, 51, 93, 0,108,105,109,105,116,109,105,110, 91, 51, 93, 0,108,105,109,105,116,109, 97,120, 91, 51, - 93, 0,115,116,105,102,102,110,101,115,115, 91, 51, 93, 0,105,107,115,116,114,101,116, 99,104, 0,105,107,114,111,116,119,101, -105,103,104,116, 0,105,107,108,105,110,119,101,105,103,104,116, 0, 42,116,101,109,112, 0, 99,104, 97,110, 98, 97,115,101, 0, - 42, 99,104, 97,110,104, 97,115,104, 0,112,114,111,120,121, 95,108, 97,121,101,114, 0,115,116,114,105,100,101, 95,111,102,102, -115,101,116, 91, 51, 93, 0, 99,121, 99,108,105, 99, 95,111,102,102,115,101,116, 91, 51, 93, 0, 97,103,114,111,117,112,115, 0, - 97, 99,116,105,118,101, 95,103,114,111,117,112, 0,105,107,115,111,108,118,101,114, 0, 42,105,107,100, 97,116, 97, 0, 42,105, -107,112, 97,114, 97,109, 0,112,114,111,120,121, 95, 97, 99,116, 95, 98,111,110,101, 91, 54, 52, 93, 0,110,117,109,105,116,101, -114, 0,110,117,109,115,116,101,112, 0,109,105,110,115,116,101,112, 0,109, 97,120,115,116,101,112, 0,115,111,108,118,101,114, - 0,102,101,101,100, 98, 97, 99,107, 0,109, 97,120,118,101,108, 0,100, 97,109,112,109, 97,120, 0,100, 97,109,112,101,112,115, - 0, 99,104, 97,110,110,101,108,115, 0, 99,117,115,116,111,109, 67,111,108, 0, 99,115, 0, 99,117,114,118,101,115, 0,103,114, -111,117,112,115, 0, 97, 99,116,105,118,101, 95,109, 97,114,107,101,114, 0,105,100,114,111,111,116, 0, 42,115,111,117,114, 99, -101, 0, 42,102,105,108,116,101,114, 95,103,114,112, 0,115,101, 97,114, 99,104,115,116,114, 91, 54, 52, 93, 0,102,105,108,116, -101,114,102,108, 97,103, 0,114,101,110, 97,109,101, 73,110,100,101,120, 0, 97,100,115, 0,116,105,109,101,115,108,105,100,101, - 0, 42,103,114,112, 0,110, 97,109,101, 91, 51, 48, 93, 0,111,119,110,115,112, 97, 99,101, 0,116, 97,114,115,112, 97, 99,101, - 0,101,110,102,111,114, 99,101, 0,104,101, 97,100,116, 97,105,108, 0,108,105,110, 95,101,114,114,111,114, 0,114,111,116, 95, -101,114,114,111,114, 0, 42,116, 97,114, 0,109, 97,116,114,105,120, 91, 52, 93, 91, 52, 93, 0,115,112, 97, 99,101, 0,114,111, -116, 79,114,100,101,114, 0,116, 97,114,110,117,109, 0,116, 97,114,103,101,116,115, 0,105,116,101,114, 97,116,105,111,110,115, - 0,114,111,111,116, 98,111,110,101, 0,109, 97,120, 95,114,111,111,116, 98,111,110,101, 0, 42,112,111,108,101,116, 97,114, 0, -112,111,108,101,115,117, 98,116, 97,114,103,101,116, 91, 54, 52, 93, 0,112,111,108,101, 97,110,103,108,101, 0,111,114,105,101, -110,116,119,101,105,103,104,116, 0,103,114, 97, 98,116, 97,114,103,101,116, 91, 51, 93, 0,110,117,109,112,111,105,110,116,115, - 0, 99,104, 97,105,110,108,101,110, 0,120,122, 83, 99, 97,108,101, 77,111,100,101, 0,114,101,115,101,114,118,101,100, 49, 0, -114,101,115,101,114,118,101,100, 50, 0,109,105,110,109, 97,120,102,108, 97,103, 0,115,116,117, 99,107, 0, 99, 97, 99,104,101, - 91, 51, 93, 0,108,111, 99,107,102,108, 97,103, 0,102,111,108,108,111,119,102,108, 97,103, 0,118,111,108,109,111,100,101, 0, -112,108, 97,110,101, 0,111,114,103,108,101,110,103,116,104, 0, 98,117,108,103,101, 0,112,105,118, 88, 0,112,105,118, 89, 0, -112,105,118, 90, 0, 97,120, 88, 0, 97,120, 89, 0, 97,120, 90, 0,109,105,110, 76,105,109,105,116, 91, 54, 93, 0,109, 97,120, - 76,105,109,105,116, 91, 54, 93, 0,101,120,116,114, 97, 70,122, 0,105,110,118,109, 97,116, 91, 52, 93, 91, 52, 93, 0,102,114, -111,109, 0,116,111, 0,109, 97,112, 91, 51, 93, 0,101,120,112,111, 0,102,114,111,109, 95,109,105,110, 91, 51, 93, 0,102,114, -111,109, 95,109, 97,120, 91, 51, 93, 0,116,111, 95,109,105,110, 91, 51, 93, 0,116,111, 95,109, 97,120, 91, 51, 93, 0,114,111, -116, 65,120,105,115, 0,122,109,105,110, 0,122,109, 97,120, 0,112, 97,100, 91, 57, 93, 0,116,114, 97, 99,107, 91, 54, 52, 93, - 0,111, 98,106,101, 99,116, 91, 54, 52, 93, 0, 42,100,101,112,116,104, 95,111, 98, 0, 99,104, 97,110,110,101,108, 91, 51, 50, - 93, 0,110,111, 95,114,111,116, 95, 97,120,105,115, 0,115,116,114,105,100,101, 95, 97,120,105,115, 0, 99,117,114,109,111,100, - 0, 97, 99,116,115,116, 97,114,116, 0, 97, 99,116,101,110,100, 0, 97, 99,116,111,102,102,115, 0,115,116,114,105,100,101,108, -101,110, 0, 98,108,101,110,100,111,117,116, 0,115,116,114,105,100,101, 99,104, 97,110,110,101,108, 91, 51, 50, 93, 0,111,102, -102,115, 95, 98,111,110,101, 91, 51, 50, 93, 0,104, 97,115,105,110,112,117,116, 0,104, 97,115,111,117,116,112,117,116, 0,100, - 97,116, 97,116,121,112,101, 0,115,111, 99,107,101,116,116,121,112,101, 0,105,115, 95, 99,111,112,121, 0,101,120,116,101,114, -110, 97,108, 0, 42,110,101,119, 95,115,111, 99,107, 0, 42,115,116,111,114, 97,103,101, 0,108,105,109,105,116, 0,115,116,114, -117, 99,116, 95,116,121,112,101, 0,108,111, 99,120, 0,108,111, 99,121, 0, 42,100,101,102, 97,117,108,116, 95,118, 97,108,117, -101, 0,115,116, 97, 99,107, 95,105,110,100,101,120, 0,115,116, 97, 99,107, 95,116,121,112,101, 0,111,119,110, 95,105,110,100, -101,120, 0,116,111, 95,105,110,100,101,120, 0, 42,103,114,111,117,112,115,111, 99,107, 0, 42,108,105,110,107, 0,110,115, 0, - 42,114,101, 99,116, 0,120,115,105,122,101, 0,121,115,105,122,101, 0, 42,110,101,119, 95,110,111,100,101, 0,108, 97,115,116, -121, 0,111,117,116,112,117,116,115, 0,109,105,110,105,119,105,100,116,104, 0,117,112,100, 97,116,101, 0,108, 97, 98,101,108, - 91, 54, 52, 93, 0, 99,117,115,116,111,109, 49, 0, 99,117,115,116,111,109, 50, 0, 99,117,115,116,111,109, 51, 0, 99,117,115, -116,111,109, 52, 0,110,101,101,100, 95,101,120,101, 99, 0,101,120,101, 99, 0, 42,116,104,114,101, 97,100,100, 97,116, 97, 0, -116,111,116,114, 0, 98,117,116,114, 0,112,114,118,114, 0, 42, 98,108,111, 99,107, 0, 42,116,121,112,101,105,110,102,111, 0, - 42,102,114,111,109,110,111,100,101, 0, 42,116,111,110,111,100,101, 0, 42,102,114,111,109,115,111, 99,107, 0, 42,116,111,115, -111, 99,107, 0,110,111,100,101,115, 0,108,105,110,107,115, 0,105,110,105,116, 0, 99,117,114, 95,105,110,100,101,120, 0,110, -111,100,101,116,121,112,101, 0, 42,101,120,101, 99,100, 97,116, 97, 0, 40, 42,112,114,111,103,114,101,115,115, 41, 40, 41, 0, - 40, 42,115,116, 97,116,115, 95,100,114, 97,119, 41, 40, 41, 0, 40, 42,116,101,115,116, 95, 98,114,101, 97,107, 41, 40, 41, 0, - 42,116, 98,104, 0, 42,112,114,104, 0, 42,115,100,104, 0,118, 97,108,117,101, 91, 51, 93, 0,118, 97,108,117,101, 91, 52, 93, - 0, 99,121, 99,108,105, 99, 0,109,111,118,105,101, 0,115, 97,109,112,108,101,115, 0,109, 97,120,115,112,101,101,100, 0,109, -105,110,115,112,101,101,100, 0, 99,117,114,118,101,100, 0,112,101,114, 99,101,110,116,120, 0,112,101,114, 99,101,110,116,121, - 0, 98,111,107,101,104, 0,103, 97,109,109, 97, 0,105,109, 97,103,101, 95,105,110, 95,119,105,100,116,104, 0,105,109, 97,103, -101, 95,105,110, 95,104,101,105,103,104,116, 0, 99,101,110,116,101,114, 95,120, 0, 99,101,110,116,101,114, 95,121, 0,115,112, -105,110, 0,119,114, 97,112, 0,115,105,103,109, 97, 95, 99,111,108,111,114, 0,115,105,103,109, 97, 95,115,112, 97, 99,101, 0, -104,117,101, 0, 98, 97,115,101, 95,112, 97,116,104, 91, 49, 48, 50, 52, 93, 0,102,111,114,109, 97,116, 0, 97, 99,116,105,118, -101, 95,105,110,112,117,116, 0,117,115,101, 95,114,101,110,100,101,114, 95,102,111,114,109, 97,116, 0,117,115,101, 95,110,111, -100,101, 95,102,111,114,109, 97,116, 0,116, 49, 0,116, 50, 0,116, 51, 0,102,115,116,114,101,110,103,116,104, 0,102, 97,108, -112,104, 97, 0,107,101,121, 91, 52, 93, 0, 97,108,103,111,114,105,116,104,109, 0, 99,104, 97,110,110,101,108, 0,120, 49, 0, -120, 50, 0,121, 49, 0,121, 50, 0,102, 97, 99, 95,120, 49, 0,102, 97, 99, 95,120, 50, 0,102, 97, 99, 95,121, 49, 0,102, 97, - 99, 95,121, 50, 0, 99,111,108,110, 97,109,101, 91, 54, 52, 93, 0, 98,107,116,121,112,101, 0,112, 97,100, 95, 99, 49, 0,103, - 97,109, 99,111, 0,110,111, 95,122, 98,117,102, 0,102,115,116,111,112, 0,109, 97,120, 98,108,117,114, 0, 98,116,104,114,101, -115,104, 0,114,111,116, 97,116,105,111,110, 0,112, 97,100, 95,102, 49, 0, 42,100,105, 99,116, 0, 42,110,111,100,101, 0, 99, -111,108,109,111,100, 0,109,105,120, 0,102, 97,100,101, 0, 97,110,103,108,101, 95,111,102,115, 0,109, 0, 99, 0,106,105,116, - 0,112,114,111,106, 0,102,105,116, 0,115,108,111,112,101, 91, 51, 93, 0,112,111,119,101,114, 91, 51, 93, 0,108,105,102,116, - 95,108,103,103, 91, 51, 93, 0,103, 97,109,109, 97, 95,105,110,118, 91, 51, 93, 0,108,105,109, 99,104, 97,110, 0,117,110,115, -112,105,108,108, 0,108,105,109,115, 99, 97,108,101, 0,117,115,112,105,108,108,114, 0,117,115,112,105,108,108,103, 0,117,115, -112,105,108,108, 98, 0,116,101,120, 95,109, 97,112,112,105,110,103, 0, 99,111,108,111,114, 95,109, 97,112,112,105,110,103, 0, -115,117,110, 95,100,105,114,101, 99,116,105,111,110, 91, 51, 93, 0,116,117,114, 98,105,100,105,116,121, 0, 99,111,108,111,114, - 95,115,112, 97, 99,101, 0,112,114,111,106,101, 99,116,105,111,110, 0,103,114, 97,100,105,101,110,116, 95,116,121,112,101, 0, - 99,111,108,111,114,105,110,103, 0,109,117,115,103,114, 97,118,101, 95,116,121,112,101, 0,119, 97,118,101, 95,116,121,112,101, - 0,115,104,111,114,116,121, 0,109,105,110,116, 97, 98,108,101, 0,109, 97,120,116, 97, 98,108,101, 0,101,120,116, 95,105,110, - 91, 50, 93, 0,101,120,116, 95,111,117,116, 91, 50, 93, 0, 42, 99,117,114,118,101, 0, 42,116, 97, 98,108,101, 0, 42,112,114, -101,109,117,108,116, 97, 98,108,101, 0,112,114,101,115,101,116, 0, 99,104, 97,110,103,101,100, 95,116,105,109,101,115,116, 97, -109,112, 0, 99,117,114,114, 0, 99,108,105,112,114, 0, 99,109, 91, 52, 93, 0, 98,108, 97, 99,107, 91, 51, 93, 0,119,104,105, -116,101, 91, 51, 93, 0, 98,119,109,117,108, 91, 51, 93, 0,115, 97,109,112,108,101, 91, 51, 93, 0,120, 95,114,101,115,111,108, -117,116,105,111,110, 0,100, 97,116, 97, 95,114, 91, 50, 53, 54, 93, 0,100, 97,116, 97, 95,103, 91, 50, 53, 54, 93, 0,100, 97, -116, 97, 95, 98, 91, 50, 53, 54, 93, 0,100, 97,116, 97, 95,108,117,109, 97, 91, 50, 53, 54, 93, 0,115, 97,109,112,108,101, 95, -102,117,108,108, 0,115, 97,109,112,108,101, 95,108,105,110,101,115, 0, 97, 99, 99,117,114, 97, 99,121, 0,119, 97,118,101,102, -114,109, 95,109,111,100,101, 0,119, 97,118,101,102,114,109, 95, 97,108,112,104, 97, 0,119, 97,118,101,102,114,109, 95,121,102, - 97, 99, 0,119, 97,118,101,102,114,109, 95,104,101,105,103,104,116, 0,118,101, 99,115, 99,111,112,101, 95, 97,108,112,104, 97, - 0,118,101, 99,115, 99,111,112,101, 95,104,101,105,103,104,116, 0,109,105,110,109, 97,120, 91, 51, 93, 91, 50, 93, 0,104,105, -115,116, 0, 42,119, 97,118,101,102,111,114,109, 95, 49, 0, 42,119, 97,118,101,102,111,114,109, 95, 50, 0, 42,119, 97,118,101, -102,111,114,109, 95, 51, 0, 42,118,101, 99,115, 99,111,112,101, 0,119, 97,118,101,102,111,114,109, 95,116,111,116, 0,111,102, -102,115,101,116, 91, 50, 93, 0, 99,108,111,110,101, 0,109,116,101,120, 0, 42,105, 99,111,110, 95,105,109, 98,117,102, 0,105, - 99,111,110, 95,102,105,108,101,112, 97,116,104, 91, 49, 48, 50, 52, 93, 0,110,111,114,109, 97,108, 95,119,101,105,103,104,116, - 0,111, 98, 95,109,111,100,101, 0,106,105,116,116,101,114, 0,115,109,111,111,116,104, 95,115,116,114,111,107,101, 95,114, 97, -100,105,117,115, 0,115,109,111,111,116,104, 95,115,116,114,111,107,101, 95,102, 97, 99,116,111,114, 0,114, 97,116,101, 0,114, -103, 98, 91, 51, 93, 0,115, 99,117,108,112,116, 95,112,108, 97,110,101, 0,112,108, 97,110,101, 95,111,102,102,115,101,116, 0, -115, 99,117,108,112,116, 95,116,111,111,108, 0,118,101,114,116,101,120,112, 97,105,110,116, 95,116,111,111,108, 0,105,109, 97, -103,101,112, 97,105,110,116, 95,116,111,111,108, 0,112, 97,100, 51, 91, 53, 93, 0, 97,117,116,111,115,109,111,111,116,104, 95, -102, 97, 99,116,111,114, 0, 99,114,101, 97,115,101, 95,112,105,110, 99,104, 95,102, 97, 99,116,111,114, 0,112,108, 97,110,101, - 95,116,114,105,109, 0,116,101,120,116,117,114,101, 95,115, 97,109,112,108,101, 95, 98,105, 97,115, 0,116,101,120,116,117,114, -101, 95,111,118,101,114,108, 97,121, 95, 97,108,112,104, 97, 0, 97,100,100, 95, 99,111,108, 91, 51, 93, 0,115,117, 98, 95, 99, -111,108, 91, 51, 93, 0, 97, 99,116,105,118,101, 95,114,110,100, 0, 97, 99,116,105,118,101, 95, 99,108,111,110,101, 0, 97, 99, -116,105,118,101, 95,109, 97,115,107, 0, 42,108, 97,121,101,114,115, 0,116,121,112,101,109, 97,112, 91, 51, 52, 93, 0,116,111, -116,108, 97,121,101,114, 0,109, 97,120,108, 97,121,101,114, 0,116,111,116,115,105,122,101, 0, 42,112,111,111,108, 0, 42,101, -120,116,101,114,110, 97,108, 0,114,111,116, 91, 52, 93, 0, 97,118,101, 91, 51, 93, 0, 42,103,114,111,117,110,100, 0,119, 97, -110,100,101,114, 91, 51, 93, 0,114,101,115,116, 95,108,101,110,103,116,104, 0,112, 97,114,116,105, 99,108,101, 95,105,110,100, -101,120, 91, 50, 93, 0,100,101,108,101,116,101, 95,102,108, 97,103, 0,110,117,109, 0,112, 97,114,101,110,116, 0,112, 97, 91, - 52, 93, 0,119, 91, 52, 93, 0,102,117,118, 91, 52, 93, 0,102,111,102,102,115,101,116, 0,112,114,101,118, 95,115,116, 97,116, -101, 0, 42,104, 97,105,114, 0, 42, 98,111,105,100, 0,100,105,101,116,105,109,101, 0,110,117,109, 95,100,109, 99, 97, 99,104, -101, 0,104, 97,105,114, 95,105,110,100,101,120, 0, 97,108,105,118,101, 0,115,112,114,105,110,103, 95,107, 0,112,108, 97,115, -116,105, 99,105,116,121, 95, 99,111,110,115,116, 97,110,116, 0,121,105,101,108,100, 95,114, 97,116,105,111, 0,112,108, 97,115, -116,105, 99,105,116,121, 95, 98, 97,108, 97,110, 99,101, 0,121,105,101,108,100, 95, 98, 97,108, 97,110, 99,101, 0,118,105,115, - 99,111,115,105,116,121, 95,111,109,101,103, 97, 0,118,105,115, 99,111,115,105,116,121, 95, 98,101,116, 97, 0,115,116,105,102, -102,110,101,115,115, 95,107, 0,115,116,105,102,102,110,101,115,115, 95,107,110,101, 97,114, 0,114,101,115,116, 95,100,101,110, -115,105,116,121, 0, 98,117,111,121, 97,110, 99,121, 0,115,112,114,105,110,103, 95,102,114, 97,109,101,115, 0, 42, 98,111,105, -100,115, 0, 42,102,108,117,105,100, 0,100,105,115,116,114, 0,112,104,121,115,116,121,112,101, 0, 97,118,101,109,111,100,101, - 0,114,101, 97, 99,116,101,118,101,110,116, 0,100,114, 97,119, 0,100,114, 97,119, 95, 97,115, 0,100,114, 97,119, 95,115,105, -122,101, 0, 99,104,105,108,100,116,121,112,101, 0,114,101,110, 95, 97,115, 0,115,117, 98,102,114, 97,109,101,115, 0,100,114, - 97,119, 95, 99,111,108, 0,114,101,110, 95,115,116,101,112, 0,104, 97,105,114, 95,115,116,101,112, 0,107,101,121,115, 95,115, -116,101,112, 0, 97,100, 97,112,116, 95, 97,110,103,108,101, 0, 97,100, 97,112,116, 95,112,105,120, 0,114,111,116,102,114,111, -109, 0,105,110,116,101,103,114, 97,116,111,114, 0, 98, 98, 95, 97,108,105,103,110, 0, 98, 98, 95,117,118, 95,115,112,108,105, -116, 0, 98, 98, 95, 97,110,105,109, 0, 98, 98, 95,115,112,108,105,116, 95,111,102,102,115,101,116, 0, 98, 98, 95,116,105,108, -116, 0, 98, 98, 95,114, 97,110,100, 95,116,105,108,116, 0, 98, 98, 95,111,102,102,115,101,116, 91, 50, 93, 0, 98, 98, 95,115, -105,122,101, 91, 50, 93, 0, 98, 98, 95,118,101,108, 95,104,101, 97,100, 0, 98, 98, 95,118,101,108, 95,116, 97,105,108, 0, 99, -111,108,111,114, 95,118,101, 99, 95,109, 97,120, 0,115,105,109,112,108,105,102,121, 95,114,101,102,115,105,122,101, 0,115,105, -109,112,108,105,102,121, 95,114, 97,116,101, 0,115,105,109,112,108,105,102,121, 95,116,114, 97,110,115,105,116,105,111,110, 0, -115,105,109,112,108,105,102,121, 95,118,105,101,119,112,111,114,116, 0,116,105,109,101,116,119,101, 97,107, 0, 99,111,117,114, - 97,110,116, 95,116, 97,114,103,101,116, 0,106,105,116,102, 97, 99, 0,101,102,102, 95,104, 97,105,114, 0,103,114,105,100, 95, -114, 97,110,100, 0,112,115, 95,111,102,102,115,101,116, 91, 49, 93, 0,103,114,105,100, 95,114,101,115, 0,101,102,102,101, 99, -116,111,114, 95, 97,109,111,117,110,116, 0,116,105,109,101, 95,102,108, 97,103, 0,116,105,109,101, 95,112, 97,100, 91, 51, 93, - 0,112, 97,114,116,102, 97, 99, 0,116, 97,110,102, 97, 99, 0,116, 97,110,112,104, 97,115,101, 0,114,101, 97, 99,116,102, 97, - 99, 0,111, 98, 95,118,101,108, 91, 51, 93, 0, 97,118,101,102, 97, 99, 0,112,104, 97,115,101,102, 97, 99, 0,114, 97,110,100, -114,111,116,102, 97, 99, 0,114, 97,110,100,112,104, 97,115,101,102, 97, 99, 0,114, 97,110,100,115,105,122,101, 0, 97, 99, 99, - 91, 51, 93, 0,100,114, 97,103,102, 97, 99, 0, 98,114,111,119,110,102, 97, 99, 0,114, 97,110,100,108,101,110,103,116,104, 0, - 99,104,105,108,100, 95,110, 98,114, 0,114,101,110, 95, 99,104,105,108,100, 95,110, 98,114, 0,112, 97,114,101,110,116,115, 0, - 99,104,105,108,100,115,105,122,101, 0, 99,104,105,108,100,114, 97,110,100,115,105,122,101, 0, 99,104,105,108,100,114, 97,100, - 0, 99,104,105,108,100,102,108, 97,116, 0, 99,108,117,109,112,112,111,119, 0,107,105,110,107, 95,102,108, 97,116, 0,107,105, -110,107, 95, 97,109,112, 95, 99,108,117,109,112, 0,114,111,117,103,104, 49, 0,114,111,117,103,104, 49, 95,115,105,122,101, 0, -114,111,117,103,104, 50, 0,114,111,117,103,104, 50, 95,115,105,122,101, 0,114,111,117,103,104, 50, 95,116,104,114,101,115, 0, -114,111,117,103,104, 95,101,110,100, 0,114,111,117,103,104, 95,101,110,100, 95,115,104, 97,112,101, 0, 99,108,101,110,103,116, -104, 0, 99,108,101,110,103,116,104, 95,116,104,114,101,115, 0,112, 97,114,116,105,110,103, 95,102, 97, 99, 0,112, 97,114,116, -105,110,103, 95,109,105,110, 0,112, 97,114,116,105,110,103, 95,109, 97,120, 0, 98,114, 97,110, 99,104, 95,116,104,114,101,115, - 0,100,114, 97,119, 95,108,105,110,101, 91, 50, 93, 0,112, 97,116,104, 95,115,116, 97,114,116, 0,112, 97,116,104, 95,101,110, -100, 0,116,114, 97,105,108, 95, 99,111,117,110,116, 0,107,101,121,101,100, 95,108,111,111,112,115, 0,100,117,112,108,105,119, -101,105,103,104,116,115, 0, 42,101,102,102, 95,103,114,111,117,112, 0, 42,100,117,112, 95,111, 98, 0, 42, 98, 98, 95,111, 98, - 0, 42,112,100, 50, 0, 42,112, 97,114,116, 0, 42,112, 97,114,116,105, 99,108,101,115, 0, 42, 42,112, 97,116,104, 99, 97, 99, -104,101, 0, 42, 42, 99,104,105,108,100, 99, 97, 99,104,101, 0,112, 97,116,104, 99, 97, 99,104,101, 98,117,102,115, 0, 99,104, -105,108,100, 99, 97, 99,104,101, 98,117,102,115, 0, 42, 99,108,109,100, 0, 42,104, 97,105,114, 95,105,110, 95,100,109, 0, 42, -104, 97,105,114, 95,111,117,116, 95,100,109, 0, 42,116, 97,114,103,101,116, 95,111, 98, 0, 42,108, 97,116,116,105, 99,101, 0, -116,114,101,101, 95,102,114, 97,109,101, 0, 98,118,104,116,114,101,101, 95,102,114, 97,109,101, 0, 99,104,105,108,100, 95,115, -101,101,100, 0,116,111,116,117,110,101,120,105,115,116, 0,116,111,116, 99,104,105,108,100, 0,116,111,116, 99, 97, 99,104,101, -100, 0,116,111,116, 99,104,105,108,100, 99, 97, 99,104,101, 0,116, 97,114,103,101,116, 95,112,115,121,115, 0,116,111,116,107, -101,121,101,100, 0, 98, 97,107,101,115,112, 97, 99,101, 0, 98, 98, 95,117,118,110, 97,109,101, 91, 51, 93, 91, 54, 52, 93, 0, -118,103,114,111,117,112, 91, 49, 50, 93, 0,118,103, 95,110,101,103, 0,114,116, 51, 0, 42,114,101,110,100,101,114,100, 97,116, - 97, 0, 42,101,102,102,101, 99,116,111,114,115, 0, 42,102,108,117,105,100, 95,115,112,114,105,110,103,115, 0,116,111,116, 95, -102,108,117,105,100,115,112,114,105,110,103,115, 0, 97,108,108,111, 99, 95,102,108,117,105,100,115,112,114,105,110,103,115, 0, - 42,116,114,101,101, 0, 42,112,100,100, 0, 42,102,114, 97,110,100, 0,100,116, 95,102,114, 97, 99, 0, 95,112, 97,100, 0, 67, -100,105,115, 0, 67,118,105, 0,115,116,114,117, 99,116,117,114, 97,108, 0, 98,101,110,100,105,110,103, 0,109, 97,120, 95, 98, -101,110,100, 0,109, 97,120, 95,115,116,114,117, 99,116, 0,109, 97,120, 95,115,104,101, 97,114, 0, 97,118,103, 95,115,112,114, -105,110,103, 95,108,101,110, 0,116,105,109,101,115, 99, 97,108,101, 0,101,102,102, 95,102,111,114, 99,101, 95,115, 99, 97,108, -101, 0,101,102,102, 95,119,105,110,100, 95,115, 99, 97,108,101, 0,115,105,109, 95,116,105,109,101, 95,111,108,100, 0,118,101, -108,111, 99,105,116,121, 95,115,109,111,111,116,104, 0, 99,111,108,108,105,100,101,114, 95,102,114,105, 99,116,105,111,110, 0, -118,101,108, 95,100, 97,109,112,105,110,103, 0,115,116,101,112,115, 80,101,114, 70,114, 97,109,101, 0,112,114,101,114,111,108, -108, 0,109, 97,120,115,112,114,105,110,103,108,101,110, 0,115,111,108,118,101,114, 95,116,121,112,101, 0,118,103,114,111,117, -112, 95, 98,101,110,100, 0,118,103,114,111,117,112, 95,109, 97,115,115, 0,118,103,114,111,117,112, 95,115,116,114,117, 99,116, - 0,115,104, 97,112,101,107,101,121, 95,114,101,115,116, 0,112,114,101,115,101,116,115, 0,114,101,115,101,116, 0, 42, 99,111, -108,108,105,115,105,111,110, 95,108,105,115,116, 0,101,112,115,105,108,111,110, 0,115,101,108,102, 95,102,114,105, 99,116,105, -111,110, 0,115,101,108,102,101,112,115,105,108,111,110, 0,114,101,112,101,108, 95,102,111,114, 99,101, 0,100,105,115,116, 97, -110, 99,101, 95,114,101,112,101,108, 0,115,101,108,102, 95,108,111,111,112, 95, 99,111,117,110,116, 0,108,111,111,112, 95, 99, -111,117,110,116, 0,112,114,101,115,115,117,114,101, 0,116,104,105, 99,107,110,101,115,115, 0,115,116,114,111,107,101,115, 0, -102,114, 97,109,101,110,117,109, 0, 42, 97, 99,116,102,114, 97,109,101, 0,103,115,116,101,112, 0,105,110,102,111, 91, 49, 50, - 56, 93, 0,115, 98,117,102,102,101,114, 95,115,105,122,101, 0,115, 98,117,102,102,101,114, 95,115,102,108, 97,103, 0, 42,115, - 98,117,102,102,101,114, 0,108,105,115,116, 0,112,114,105,110,116,108,101,118,101,108, 0,115,116,111,114,101,108,101,118,101, -108, 0, 42,114,101,112,111,114,116,116,105,109,101,114, 0, 42,119,105,110,100,114, 97,119, 97, 98,108,101, 0, 42,119,105,110, - 97, 99,116,105,118,101, 0,119,105,110,100,111,119,115, 0,105,110,105,116,105, 97,108,105,122,101,100, 0,102,105,108,101, 95, -115, 97,118,101,100, 0,111,112, 95,117,110,100,111, 95,100,101,112,116,104, 0,111,112,101,114, 97,116,111,114,115, 0,113,117, -101,117,101, 0,114,101,112,111,114,116,115, 0,106,111, 98,115, 0,112, 97,105,110,116, 99,117,114,115,111,114,115, 0,100,114, - 97,103,115, 0,107,101,121, 99,111,110,102,105,103,115, 0, 42,100,101,102, 97,117,108,116, 99,111,110,102, 0, 42, 97,100,100, -111,110, 99,111,110,102, 0, 42,117,115,101,114, 99,111,110,102, 0,116,105,109,101,114,115, 0, 42, 97,117,116,111,115, 97,118, -101,116,105,109,101,114, 0, 42,103,104,111,115,116,119,105,110, 0,103,114, 97, 98, 99,117,114,115,111,114, 0, 42,115, 99,114, -101,101,110, 0, 42,110,101,119,115, 99,114,101,101,110, 0,115, 99,114,101,101,110,110, 97,109,101, 91, 54, 52, 93, 0,112,111, -115,120, 0,112,111,115,121, 0,119,105,110,100,111,119,115,116, 97,116,101, 0,109,111,110,105,116,111,114, 0,108, 97,115,116, - 99,117,114,115,111,114, 0,109,111,100, 97,108, 99,117,114,115,111,114, 0, 97,100,100,109,111,117,115,101,109,111,118,101, 0, - 42,101,118,101,110,116,115,116, 97,116,101, 0, 42, 99,117,114,115,119,105,110, 0, 42,116,119,101, 97,107, 0,100,114, 97,119, -109,101,116,104,111,100, 0,100,114, 97,119,102, 97,105,108, 0, 42,100,114, 97,119,100, 97,116, 97, 0,109,111,100, 97,108,104, - 97,110,100,108,101,114,115, 0,115,117, 98,119,105,110,100,111,119,115, 0,103,101,115,116,117,114,101, 0,105,100,110, 97,109, -101, 91, 54, 52, 93, 0,112,114,111,112,118, 97,108,117,101, 0,115,104,105,102,116, 0, 99,116,114,108, 0, 97,108,116, 0,111, -115,107,101,121, 0,107,101,121,109,111,100,105,102,105,101,114, 0,109, 97,112,116,121,112,101, 0, 42,112,116,114, 0, 42,114, -101,109,111,118,101, 95,105,116,101,109, 0, 42, 97,100,100, 95,105,116,101,109, 0,105,116,101,109,115, 0,100,105,102,102, 95, -105,116,101,109,115, 0,115,112, 97, 99,101,105,100, 0,114,101,103,105,111,110,105,100, 0,107,109,105, 95,105,100, 0, 40, 42, -112,111,108,108, 41, 40, 41, 0, 42,109,111,100, 97,108, 95,105,116,101,109,115, 0, 98, 97,115,101,110, 97,109,101, 91, 54, 52, - 93, 0, 97, 99,116,107,101,121,109, 97,112, 0, 42, 99,117,115,116,111,109,100, 97,116, 97, 0, 42,112,121, 95,105,110,115,116, - 97,110, 99,101, 0, 42,114,101,112,111,114,116,115, 0,109, 97, 99,114,111, 0, 42,111,112,109, 0, 42,101,100, 97,116, 97, 0, - 42, 99,111,101,102,102,105, 99,105,101,110,116,115, 0, 97,114,114, 97,121,115,105,122,101, 0,112,111,108,121, 95,111,114,100, -101,114, 0, 97,109,112,108,105,116,117,100,101, 0,112,104, 97,115,101, 95,109,117,108,116,105,112,108,105,101,114, 0,112,104, - 97,115,101, 95,111,102,102,115,101,116, 0,118, 97,108,117,101, 95,111,102,102,115,101,116, 0,109,105,100,118, 97,108, 0, 98, -101,102,111,114,101, 95,109,111,100,101, 0, 97,102,116,101,114, 95,109,111,100,101, 0, 98,101,102,111,114,101, 95, 99,121, 99, -108,101,115, 0, 97,102,116,101,114, 95, 99,121, 99,108,101,115, 0,114,101, 99,116, 0,112,104, 97,115,101, 0,109,111,100,105, -102,105, 99, 97,116,105,111,110, 0,115,116,101,112, 95,115,105,122,101, 0, 42,114,110, 97, 95,112, 97,116,104, 0,112, 99,104, - 97,110, 95,110, 97,109,101, 91, 51, 50, 93, 0,116,114, 97,110,115, 67,104, 97,110, 0,105,100,116,121,112,101, 0,116, 97,114, -103,101,116,115, 91, 56, 93, 0,110,117,109, 95,116, 97,114,103,101,116,115, 0,118, 97,114,105, 97, 98,108,101,115, 0,101,120, -112,114,101,115,115,105,111,110, 91, 50, 53, 54, 93, 0, 42,101,120,112,114, 95, 99,111,109,112, 0,118,101, 99, 91, 50, 93, 0, - 42,102,112,116, 0, 97,114,114, 97,121, 95,105,110,100,101,120, 0, 99,111,108,111,114, 95,109,111,100,101, 0, 99,111,108,111, -114, 91, 51, 93, 0,102,114,111,109, 91, 49, 50, 56, 93, 0,116,111, 91, 49, 50, 56, 93, 0,109, 97,112,112,105,110,103,115, 0, -115,116,114,105,112,115, 0, 42,114,101,109, 97,112, 0,102, 99,117,114,118,101,115, 0,115,116,114,105,112, 95,116,105,109,101, - 0, 98,108,101,110,100,109,111,100,101, 0,101,120,116,101,110,100,109,111,100,101, 0, 42,115,112,101, 97,107,101,114, 95,104, - 97,110,100,108,101, 0,103,114,111,117,112, 91, 54, 52, 93, 0,103,114,111,117,112,109,111,100,101, 0,107,101,121,105,110,103, -102,108, 97,103, 0,112, 97,116,104,115, 0,100,101,115, 99,114,105,112,116,105,111,110, 91, 50, 52, 48, 93, 0,116,121,112,101, -105,110,102,111, 91, 54, 52, 93, 0, 97, 99,116,105,118,101, 95,112, 97,116,104, 0, 42,116,109,112, 97, 99,116, 0,110,108, 97, - 95,116,114, 97, 99,107,115, 0, 42, 97, 99,116,115,116,114,105,112, 0,100,114,105,118,101,114,115, 0,111,118,101,114,114,105, -100,101,115, 0, 97, 99,116, 95, 98,108,101,110,100,109,111,100,101, 0, 97, 99,116, 95,101,120,116,101,110,100,109,111,100,101, - 0, 97, 99,116, 95,105,110,102,108,117,101,110, 99,101, 0,114,117,108,101, 0,111,112,116,105,111,110,115, 0,102,101, 97,114, - 95,102, 97, 99,116,111,114, 0,115,105,103,110, 97,108, 95,105,100, 0,108,111,111,107, 95, 97,104,101, 97,100, 0,111,108,111, - 99, 91, 51, 93, 0,113,117,101,117,101, 95,115,105,122,101, 0,119, 97,110,100,101,114, 0,102,108,101,101, 95,100,105,115,116, - 97,110, 99,101, 0,104,101, 97,108,116,104, 0,115,116, 97,116,101, 95,105,100, 0,114,117,108,101,115, 0, 99,111,110,100,105, -116,105,111,110,115, 0, 97, 99,116,105,111,110,115, 0,114,117,108,101,115,101,116, 95,116,121,112,101, 0,114,117,108,101, 95, -102,117,122,122,105,110,101,115,115, 0,108, 97,115,116, 95,115,116, 97,116,101, 95,105,100, 0,108, 97,110,100,105,110,103, 95, -115,109,111,111,116,104,110,101,115,115, 0, 98, 97,110,107,105,110,103, 0, 97,103,103,114,101,115,115,105,111,110, 0, 97,105, -114, 95,109,105,110, 95,115,112,101,101,100, 0, 97,105,114, 95,109, 97,120, 95,115,112,101,101,100, 0, 97,105,114, 95,109, 97, -120, 95, 97, 99, 99, 0, 97,105,114, 95,109, 97,120, 95, 97,118,101, 0, 97,105,114, 95,112,101,114,115,111,110, 97,108, 95,115, -112, 97, 99,101, 0,108, 97,110,100, 95,106,117,109,112, 95,115,112,101,101,100, 0,108, 97,110,100, 95,109, 97,120, 95,115,112, -101,101,100, 0,108, 97,110,100, 95,109, 97,120, 95, 97, 99, 99, 0,108, 97,110,100, 95,109, 97,120, 95, 97,118,101, 0,108, 97, -110,100, 95,112,101,114,115,111,110, 97,108, 95,115,112, 97, 99,101, 0,108, 97,110,100, 95,115,116,105, 99,107, 95,102,111,114, - 99,101, 0,115,116, 97,116,101,115, 0, 42,115,109,100, 0, 42,102,108,117,105,100, 95,103,114,111,117,112, 0, 42, 99,111,108, -108, 95,103,114,111,117,112, 0, 42,119,116, 0, 42,116,101,120, 95,119,116, 0, 42,116,101,120, 95,115,104, 97,100,111,119, 0, - 42,115,104, 97,100,111,119, 0,112, 48, 91, 51, 93, 0,112, 49, 91, 51, 93, 0,100,120, 0,111,109,101,103, 97, 0,116,101,109, -112, 65,109, 98, 0, 98,101,116, 97, 0,114,101,115, 91, 51, 93, 0, 97,109,112,108,105,102,121, 0,109, 97,120,114,101,115, 0, -118,105,101,119,115,101,116,116,105,110,103,115, 0,110,111,105,115,101, 0,100,105,115,115, 95,112,101,114, 99,101,110,116, 0, -100,105,115,115, 95,115,112,101,101,100, 0,114,101,115, 95,119,116, 91, 51, 93, 0,100,120, 95,119,116, 0,118, 51,100,110,117, -109, 0, 99, 97, 99,104,101, 95, 99,111,109,112, 0, 99, 97, 99,104,101, 95,104,105,103,104, 95, 99,111,109,112, 0, 42,112,111, -105,110,116, 95, 99, 97, 99,104,101, 91, 50, 93, 0,112,116, 99, 97, 99,104,101,115, 91, 50, 93, 0, 98,111,114,100,101,114, 95, - 99,111,108,108,105,115,105,111,110,115, 0,116,105,109,101, 95,115, 99, 97,108,101, 0,118,111,114,116,105, 99,105,116,121, 0, -118,101,108,111, 99,105,116,121, 91, 50, 93, 0,118,101,108, 95,109,117,108,116,105, 0,118,103,114,112, 95,104,101, 97,116, 95, -115, 99, 97,108,101, 91, 50, 93, 0,118,103,114,111,117,112, 95,102,108,111,119, 0,118,103,114,111,117,112, 95,100,101,110,115, -105,116,121, 0,118,103,114,111,117,112, 95,104,101, 97,116, 0, 42,112,111,105,110,116,115, 95,111,108,100, 0, 42,118,101,108, - 0,109, 97,116, 95,111,108,100, 91, 52, 93, 91, 52, 93, 0,118,111,108,117,109,101, 95,109, 97,120, 0,118,111,108,117,109,101, - 95,109,105,110, 0,100,105,115,116, 97,110, 99,101, 95,109, 97,120, 0,100,105,115,116, 97,110, 99,101, 95,114,101,102,101,114, -101,110, 99,101, 0, 99,111,110,101, 95, 97,110,103,108,101, 95,111,117,116,101,114, 0, 99,111,110,101, 95, 97,110,103,108,101, - 95,105,110,110,101,114, 0, 99,111,110,101, 95,118,111,108,117,109,101, 95,111,117,116,101,114, 0,114,101,110,100,101,114, 95, -102,108, 97,103, 0, 98,117,105,108,100, 95,115,105,122,101, 95,102,108, 97,103, 0, 98,117,105,108,100, 95,116, 99, 95,102,108, - 97,103, 0,108, 97,115,116,115,105,122,101, 91, 50, 93, 0,116,114, 97, 99,107,105,110,103, 0, 42,116,114, 97, 99,107,105,110, -103, 95, 99,111,110,116,101,120,116, 0,112,114,111,120,121, 0,116,114, 97, 99,107, 95,112,114,101,118,105,101,119, 95,104,101, -105,103,104,116, 0, 42,116,114, 97, 99,107, 95,112,114,101,118,105,101,119, 0,116,114, 97, 99,107, 95,112,111,115, 91, 50, 93, - 0,116,114, 97, 99,107, 95,100,105,115, 97, 98,108,101,100, 0, 42,109, 97,114,107,101,114, 0,115,108,105,100,101, 95,115, 99, - 97,108,101, 91, 50, 93, 0,101,114,114,111,114, 0, 42,105,110,116,114,105,110,115,105, 99,115, 0,115,101,110,115,111,114, 95, -119,105,100,116,104, 0,112,105,120,101,108, 95, 97,115,112,101, 99,116, 0,102,111, 99, 97,108, 0,117,110,105,116,115, 0,112, -114,105,110, 99,105,112, 97,108, 91, 50, 93, 0,107, 49, 0,107, 50, 0,107, 51, 0,112,111,115, 91, 50, 93, 0,112, 97,116, 95, -109,105,110, 91, 50, 93, 0,112, 97,116, 95,109, 97,120, 91, 50, 93, 0,115,101, 97,114, 99,104, 95,109,105,110, 91, 50, 93, 0, -115,101, 97,114, 99,104, 95,109, 97,120, 91, 50, 93, 0,109, 97,114,107,101,114,115,110,114, 0,108, 97,115,116, 95,109, 97,114, -107,101,114, 0, 42,109, 97,114,107,101,114,115, 0, 98,117,110,100,108,101, 95,112,111,115, 91, 51, 93, 0,112, 97,116, 95,102, -108, 97,103, 0,115,101, 97,114, 99,104, 95,102,108, 97,103, 0,102,114, 97,109,101,115, 95,108,105,109,105,116, 0,112, 97,116, -116,101,114,110, 95,109, 97,116, 99,104, 0,116,114, 97, 99,107,101,114, 0,112,121,114, 97,109,105,100, 95,108,101,118,101,108, -115, 0,109,105,110,105,109,117,109, 95, 99,111,114,114,101,108, 97,116,105,111,110, 0,100,101,102, 97,117,108,116, 95,116,114, - 97, 99,107,101,114, 0,100,101,102, 97,117,108,116, 95,112,121,114, 97,109,105,100, 95,108,101,118,101,108,115, 0,100,101,102, - 97,117,108,116, 95,109,105,110,105,109,117,109, 95, 99,111,114,114,101,108, 97,116,105,111,110, 0,100,101,102, 97,117,108,116, - 95,112, 97,116,116,101,114,110, 95,115,105,122,101, 0,100,101,102, 97,117,108,116, 95,115,101, 97,114, 99,104, 95,115,105,122, -101, 0,100,101,102, 97,117,108,116, 95,102,114, 97,109,101,115, 95,108,105,109,105,116, 0,100,101,102, 97,117,108,116, 95,109, - 97,114,103,105,110, 0,100,101,102, 97,117,108,116, 95,112, 97,116,116,101,114,110, 95,109, 97,116, 99,104, 0,100,101,102, 97, -117,108,116, 95,102,108, 97,103, 0,112,111,100, 0,107,101,121,102,114, 97,109,101, 49, 0,107,101,121,102,114, 97,109,101, 50, - 0,114,101,102,105,110,101, 95, 99, 97,109,101,114, 97, 95,105,110,116,114,105,110,115,105, 99,115, 0,112, 97,100, 50, 51, 0, - 99,108,101, 97,110, 95,102,114, 97,109,101,115, 0, 99,108,101, 97,110, 95, 97, 99,116,105,111,110, 0, 99,108,101, 97,110, 95, -101,114,114,111,114, 0,111, 98,106,101, 99,116, 95,100,105,115,116, 97,110, 99,101, 0,116,111,116, 95,116,114, 97, 99,107, 0, - 97, 99,116, 95,116,114, 97, 99,107, 0,109, 97,120,115, 99, 97,108,101, 0, 42,114,111,116, 95,116,114, 97, 99,107, 0,108,111, - 99,105,110,102, 0,115, 99, 97,108,101,105,110,102, 0,114,111,116,105,110,102, 0, 42,115, 99, 97,108,101,105, 98,117,102, 0, -108, 97,115,116, 95, 99, 97,109,101,114, 97, 0, 99, 97,109,110,114, 0, 42, 99, 97,109,101,114, 97,115, 0,116,114, 97, 99,107, -115, 0,114,101, 99,111,110,115,116,114,117, 99,116,105,111,110, 0,109,101,115,115, 97,103,101, 91, 50, 53, 54, 93, 0,115,101, -116,116,105,110,103,115, 0, 99, 97,109,101,114, 97, 0,115,116, 97, 98,105,108,105,122, 97,116,105,111,110, 0, 42, 97, 99,116, - 95,116,114, 97, 99,107, 0,111, 98,106,101, 99,116,115, 0,111, 98,106,101, 99,116,110,114, 0,116,111,116, 95,111, 98,106,101, - 99,116, 0, 42, 98,114,117,115,104, 95,103,114,111,117,112, 0, 99,117,114,114,101,110,116, 95,102,114, 97,109,101, 0,100,105, -115,112, 95,116,121,112,101, 0,105,109, 97,103,101, 95,102,105,108,101,102,111,114,109, 97,116, 0,101,102,102,101, 99,116, 95, -117,105, 0,112,114,101,118,105,101,119, 95,105,100, 0,105,110,105,116, 95, 99,111,108,111,114, 95,116,121,112,101, 0,112, 97, -100, 95,115, 0,105,109, 97,103,101, 95,114,101,115,111,108,117,116,105,111,110, 0,115,117, 98,115,116,101,112,115, 0,105,110, -105,116, 95, 99,111,108,111,114, 91, 52, 93, 0, 42,105,110,105,116, 95,116,101,120,116,117,114,101, 0,105,110,105,116, 95,108, - 97,121,101,114,110, 97,109,101, 91, 54, 52, 93, 0,100,114,121, 95,115,112,101,101,100, 0, 99,111,108,111,114, 95,100,114,121, - 95,116,104,114,101,115,104,111,108,100, 0,100,101,112,116,104, 95, 99,108, 97,109,112, 0,100,105,115,112, 95,102, 97, 99,116, -111,114, 0,115,112,114,101, 97,100, 95,115,112,101,101,100, 0, 99,111,108,111,114, 95,115,112,114,101, 97,100, 95,115,112,101, -101,100, 0,115,104,114,105,110,107, 95,115,112,101,101,100, 0,100,114,105,112, 95,118,101,108, 0,100,114,105,112, 95, 97, 99, - 99, 0,105,110,102,108,117,101,110, 99,101, 95,115, 99, 97,108,101, 0,114, 97,100,105,117,115, 95,115, 99, 97,108,101, 0,119, - 97,118,101, 95,100, 97,109,112,105,110,103, 0,119, 97,118,101, 95,115,112,101,101,100, 0,119, 97,118,101, 95,116,105,109,101, -115, 99, 97,108,101, 0,119, 97,118,101, 95,115,112,114,105,110,103, 0,105,109, 97,103,101, 95,111,117,116,112,117,116, 95,112, - 97,116,104, 91, 49, 48, 50, 52, 93, 0,111,117,116,112,117,116, 95,110, 97,109,101, 91, 54, 52, 93, 0,111,117,116,112,117,116, - 95,110, 97,109,101, 50, 91, 54, 52, 93, 0, 42,112,109,100, 0,115,117,114,102, 97, 99,101,115, 0, 97, 99,116,105,118,101, 95, -115,117,114, 0,101,114,114,111,114, 91, 54, 52, 93, 0, 99,111,108,108,105,115,105,111,110, 0,119,101,116,110,101,115,115, 0, -112, 97,114,116,105, 99,108,101, 95,114, 97,100,105,117,115, 0,112, 97,114,116,105, 99,108,101, 95,115,109,111,111,116,104, 0, -112, 97,105,110,116, 95,100,105,115,116, 97,110, 99,101, 0, 42,112, 97,105,110,116, 95,114, 97,109,112, 0, 42,118,101,108, 95, -114, 97,109,112, 0,112,114,111,120,105,109,105,116,121, 95,102, 97,108,108,111,102,102, 0,114, 97,121, 95,100,105,114, 0,119, - 97,118,101, 95,102, 97, 99,116,111,114, 0,119, 97,118,101, 95, 99,108, 97,109,112, 0,109, 97,120, 95,118,101,108,111, 99,105, -116,121, 0,115,109,117,100,103,101, 95,115,116,114,101,110,103,116,104, 0, 0, 84, 89, 80, 69, 16, 2, 0, 0, 99,104, 97,114, - 0,117, 99,104, 97,114, 0,115,104,111,114,116, 0,117,115,104,111,114,116, 0,105,110,116, 0,108,111,110,103, 0,117,108,111, -110,103, 0,102,108,111, 97,116, 0,100,111,117, 98,108,101, 0,105,110,116, 54, 52, 95,116, 0,117,105,110,116, 54, 52, 95,116, - 0,118,111,105,100, 0, 76,105,110,107, 0, 76,105,110,107, 68, 97,116, 97, 0, 76,105,115,116, 66, 97,115,101, 0,118,101, 99, - 50,115, 0,118,101, 99, 50,102, 0,118,101, 99, 51,102, 0,114, 99,116,105, 0,114, 99,116,102, 0, 73, 68, 80,114,111,112,101, -114,116,121, 68, 97,116, 97, 0, 73, 68, 80,114,111,112,101,114,116,121, 0, 73, 68, 0, 76,105, 98,114, 97,114,121, 0, 70,105, -108,101, 68, 97,116, 97, 0, 80,114,101,118,105,101,119, 73,109, 97,103,101, 0, 73,112,111, 68,114,105,118,101,114, 0, 79, 98, -106,101, 99,116, 0, 73,112,111, 67,117,114,118,101, 0, 66, 80,111,105,110,116, 0, 66,101,122, 84,114,105,112,108,101, 0, 73, -112,111, 0, 75,101,121, 66,108,111, 99,107, 0, 75,101,121, 0, 65,110,105,109, 68, 97,116, 97, 0, 84,101,120,116, 76,105,110, -101, 0, 84,101,120,116, 77, 97,114,107,101,114, 0, 84,101,120,116, 0, 80, 97, 99,107,101,100, 70,105,108,101, 0, 67, 97,109, -101,114, 97, 0, 73,109, 97,103,101, 85,115,101,114, 0, 83, 99,101,110,101, 0, 73,109, 97,103,101, 0, 71, 80, 85, 84,101,120, -116,117,114,101, 0, 97,110,105,109, 0, 82,101,110,100,101,114, 82,101,115,117,108,116, 0, 77, 84,101,120, 0, 84,101,120, 0, - 80,108,117,103,105,110, 84,101,120, 0, 67, 66, 68, 97,116, 97, 0, 67,111,108,111,114, 66, 97,110,100, 0, 69,110,118, 77, 97, -112, 0, 73,109, 66,117,102, 0, 80,111,105,110,116, 68,101,110,115,105,116,121, 0, 67,117,114,118,101, 77, 97,112,112,105,110, -103, 0, 86,111,120,101,108, 68, 97,116, 97, 0, 79, 99,101, 97,110, 84,101,120, 0, 98, 78,111,100,101, 84,114,101,101, 0, 84, -101,120, 77, 97,112,112,105,110,103, 0, 67,111,108,111,114, 77, 97,112,112,105,110,103, 0, 76, 97,109,112, 0, 86,111,108,117, -109,101, 83,101,116,116,105,110,103,115, 0, 71, 97,109,101, 83,101,116,116,105,110,103,115, 0, 77, 97,116,101,114,105, 97,108, - 0, 71,114,111,117,112, 0, 86, 70,111,110,116, 0, 86, 70,111,110,116, 68, 97,116, 97, 0, 77,101,116, 97, 69,108,101,109, 0, - 66,111,117,110,100, 66,111,120, 0, 77,101,116, 97, 66, 97,108,108, 0, 78,117,114, 98, 0, 67,104, 97,114, 73,110,102,111, 0, - 84,101,120,116, 66,111,120, 0, 69,100,105,116, 78,117,114, 98, 0, 71, 72, 97,115,104, 0, 67,117,114,118,101, 0, 80, 97,116, -104, 0, 83,101,108, 66,111,120, 0, 69,100,105,116, 70,111,110,116, 0, 77,101,115,104, 0, 77, 80,111,108,121, 0, 77, 84,101, -120, 80,111,108,121, 0, 77, 76,111,111,112, 0, 77, 76,111,111,112, 85, 86, 0, 77, 76,111,111,112, 67,111,108, 0, 77, 70, 97, - 99,101, 0, 77, 84, 70, 97, 99,101, 0, 84, 70, 97, 99,101, 0, 77, 86,101,114,116, 0, 77, 69,100,103,101, 0, 77, 68,101,102, -111,114,109, 86,101,114,116, 0, 77, 67,111,108, 0, 77, 83,116,105, 99,107,121, 0, 77, 83,101,108,101, 99,116, 0, 66, 77, 69, -100,105,116, 77,101,115,104, 0, 67,117,115,116,111,109, 68, 97,116, 97, 0, 77,117,108,116,105,114,101,115, 0, 77, 68,101,102, -111,114,109, 87,101,105,103,104,116, 0, 77, 70,108,111, 97,116, 80,114,111,112,101,114,116,121, 0, 77, 73,110,116, 80,114,111, -112,101,114,116,121, 0, 77, 83,116,114,105,110,103, 80,114,111,112,101,114,116,121, 0, 79,114,105,103, 83,112, 97, 99,101, 70, - 97, 99,101, 0, 79,114,105,103, 83,112, 97, 99,101, 76,111,111,112, 0, 77, 68,105,115,112,115, 0, 77,117,108,116,105,114,101, -115, 67,111,108, 0, 77,117,108,116,105,114,101,115, 67,111,108, 70, 97, 99,101, 0, 77,117,108,116,105,114,101,115, 70, 97, 99, -101, 0, 77,117,108,116,105,114,101,115, 69,100,103,101, 0, 77,117,108,116,105,114,101,115, 76,101,118,101,108, 0, 77, 82,101, - 99, 97,115,116, 0, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77, 97,112,112,105,110,103, 73,110,102,111, 77,111,100, -105,102,105,101,114, 68, 97,116, 97, 0, 83,117, 98,115,117,114,102, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 76, 97, -116,116,105, 99,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67,117,114,118,101, 77,111,100,105,102,105,101,114, 68, - 97,116, 97, 0, 66,117,105,108,100, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77, 97,115,107, 77,111,100,105,102,105, -101,114, 68, 97,116, 97, 0, 65,114,114, 97,121, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77,105,114,114,111,114, 77, -111,100,105,102,105,101,114, 68, 97,116, 97, 0, 69,100,103,101, 83,112,108,105,116, 77,111,100,105,102,105,101,114, 68, 97,116, - 97, 0, 66,101,118,101,108, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 66, 77,101,115,104, 77,111,100,105,102,105,101, -114, 68, 97,116, 97, 0, 83,109,111,107,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,109,111,107,101, 68,111,109, - 97,105,110, 83,101,116,116,105,110,103,115, 0, 83,109,111,107,101, 70,108,111,119, 83,101,116,116,105,110,103,115, 0, 83,109, -111,107,101, 67,111,108,108, 83,101,116,116,105,110,103,115, 0, 68,105,115,112,108, 97, 99,101, 77,111,100,105,102,105,101,114, - 68, 97,116, 97, 0, 85, 86, 80,114,111,106,101, 99,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 68,101, 99,105,109, - 97,116,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,109,111,111,116,104, 77,111,100,105,102,105,101,114, 68, 97, -116, 97, 0, 67, 97,115,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 87, 97,118,101, 77,111,100,105,102,105,101,114, - 68, 97,116, 97, 0, 65,114,109, 97,116,117,114,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 72,111,111,107, 77,111, -100,105,102,105,101,114, 68, 97,116, 97, 0, 83,111,102,116, 98,111,100,121, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, - 67,108,111,116,104, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67,108,111,116,104, 0, 67,108,111,116,104, 83,105,109, - 83,101,116,116,105,110,103,115, 0, 67,108,111,116,104, 67,111,108,108, 83,101,116,116,105,110,103,115, 0, 80,111,105,110,116, - 67, 97, 99,104,101, 0, 67,111,108,108,105,115,105,111,110, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 66, 86, 72, 84, -114,101,101, 0, 83,117,114,102, 97, 99,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 68,101,114,105,118,101,100, 77, -101,115,104, 0, 66, 86, 72, 84,114,101,101, 70,114,111,109, 77,101,115,104, 0, 66,111,111,108,101, 97,110, 77,111,100,105,102, -105,101,114, 68, 97,116, 97, 0, 77, 68,101,102, 73,110,102,108,117,101,110, 99,101, 0, 77, 68,101,102, 67,101,108,108, 0, 77, -101,115,104, 68,101,102,111,114,109, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108,101, 83,121, -115,116,101,109, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108,101, 83,121,115,116,101,109, 0, - 80, 97,114,116,105, 99,108,101, 73,110,115,116, 97,110, 99,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 69,120,112, -108,111,100,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77,117,108,116,105,114,101,115, 77,111,100,105,102,105,101, -114, 68, 97,116, 97, 0, 70,108,117,105,100,115,105,109, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 70,108,117,105,100, -115,105,109, 83,101,116,116,105,110,103,115, 0, 83,104,114,105,110,107,119,114, 97,112, 77,111,100,105,102,105,101,114, 68, 97, -116, 97, 0, 83,105,109,112,108,101, 68,101,102,111,114,109, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,104, 97,112, -101, 75,101,121, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,111,108,105,100,105,102,121, 77,111,100,105,102,105,101, -114, 68, 97,116, 97, 0, 83, 99,114,101,119, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 79, 99,101, 97,110, 77,111,100, -105,102,105,101,114, 68, 97,116, 97, 0, 79, 99,101, 97,110, 0, 79, 99,101, 97,110, 67, 97, 99,104,101, 0, 87, 97,114,112, 77, -111,100,105,102,105,101,114, 68, 97,116, 97, 0, 87,101,105,103,104,116, 86, 71, 69,100,105,116, 77,111,100,105,102,105,101,114, - 68, 97,116, 97, 0, 87,101,105,103,104,116, 86, 71, 77,105,120, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 87,101,105, -103,104,116, 86, 71, 80,114,111,120,105,109,105,116,121, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 68,121,110, 97,109, -105, 99, 80, 97,105,110,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 68,121,110, 97,109,105, 99, 80, 97,105,110,116, - 67, 97,110,118, 97,115, 83,101,116,116,105,110,103,115, 0, 68,121,110, 97,109,105, 99, 80, 97,105,110,116, 66,114,117,115,104, - 83,101,116,116,105,110,103,115, 0, 82,101,109,101,115,104, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 69,100,105,116, - 76, 97,116,116, 0, 76, 97,116,116,105, 99,101, 0, 98, 68,101,102,111,114,109, 71,114,111,117,112, 0, 83, 99,117,108,112,116, - 83,101,115,115,105,111,110, 0, 98, 65, 99,116,105,111,110, 0, 98, 80,111,115,101, 0, 98, 71, 80,100, 97,116, 97, 0, 98, 65, -110,105,109, 86,105,122, 83,101,116,116,105,110,103,115, 0, 98, 77,111,116,105,111,110, 80, 97,116,104, 0, 66,117,108,108,101, -116, 83,111,102,116, 66,111,100,121, 0, 80, 97,114,116, 68,101,102,108,101, 99,116, 0, 83,111,102,116, 66,111,100,121, 0, 79, - 98, 72,111,111,107, 0, 68,117,112,108,105, 79, 98,106,101, 99,116, 0, 82, 78, 71, 0, 69,102,102,101, 99,116,111,114, 87,101, -105,103,104,116,115, 0, 80, 84, 67, 97, 99,104,101, 69,120,116,114, 97, 0, 80, 84, 67, 97, 99,104,101, 77,101,109, 0, 80, 84, - 67, 97, 99,104,101, 69,100,105,116, 0, 83, 66, 86,101,114,116,101,120, 0, 66,111,100,121, 80,111,105,110,116, 0, 66,111,100, -121, 83,112,114,105,110,103, 0, 83, 66, 83, 99,114, 97,116, 99,104, 0, 70,108,117,105,100, 86,101,114,116,101,120, 86,101,108, -111, 99,105,116,121, 0, 87,111,114,108,100, 0, 66, 97,115,101, 0, 65,118,105, 67,111,100,101, 99, 68, 97,116, 97, 0, 81,117, -105, 99,107,116,105,109,101, 67,111,100,101, 99, 68, 97,116, 97, 0, 81,117,105, 99,107,116,105,109,101, 67,111,100,101, 99, 83, -101,116,116,105,110,103,115, 0, 70, 70, 77,112,101,103, 67,111,100,101, 99, 68, 97,116, 97, 0, 65,117,100,105,111, 68, 97,116, - 97, 0, 83, 99,101,110,101, 82,101,110,100,101,114, 76, 97,121,101,114, 0, 73,109, 97,103,101, 70,111,114,109, 97,116, 68, 97, -116, 97, 0, 82,101,110,100,101,114, 68, 97,116, 97, 0, 82,101,110,100,101,114, 80,114,111,102,105,108,101, 0, 71, 97,109,101, - 68,111,109,101, 0, 71, 97,109,101, 70,114, 97,109,105,110,103, 0, 82,101, 99, 97,115,116, 68, 97,116, 97, 0, 71, 97,109,101, - 68, 97,116, 97, 0, 84,105,109,101, 77, 97,114,107,101,114, 0, 80, 97,105,110,116, 0, 66,114,117,115,104, 0, 73,109, 97,103, -101, 80, 97,105,110,116, 83,101,116,116,105,110,103,115, 0, 80, 97,114,116,105, 99,108,101, 66,114,117,115,104, 68, 97,116, 97, - 0, 80, 97,114,116,105, 99,108,101, 69,100,105,116, 83,101,116,116,105,110,103,115, 0, 83, 99,117,108,112,116, 0, 85,118, 83, - 99,117,108,112,116, 0, 86, 80, 97,105,110,116, 0, 84,114, 97,110,115,102,111,114,109, 79,114,105,101,110,116, 97,116,105,111, -110, 0, 85,110,105,102,105,101,100, 80, 97,105,110,116, 83,101,116,116,105,110,103,115, 0, 84,111,111,108, 83,101,116,116,105, -110,103,115, 0, 98, 83,116, 97,116,115, 0, 85,110,105,116, 83,101,116,116,105,110,103,115, 0, 80,104,121,115,105, 99,115, 83, -101,116,116,105,110,103,115, 0, 69,100,105,116,105,110,103, 0, 83, 99,101,110,101, 83,116, 97,116,115, 0, 68, 97,103, 70,111, -114,101,115,116, 0, 77,111,118,105,101, 67,108,105,112, 0, 66, 71,112,105, 99, 0, 77,111,118,105,101, 67,108,105,112, 85,115, -101,114, 0, 82,101,103,105,111,110, 86,105,101,119, 51, 68, 0, 82,101,110,100,101,114, 73,110,102,111, 0, 82,101,110,100,101, -114, 69,110,103,105,110,101, 0, 86,105,101,119, 68,101,112,116,104,115, 0, 83,109,111,111,116,104, 86,105,101,119, 83,116,111, -114,101, 0,119,109, 84,105,109,101,114, 0, 86,105,101,119, 51, 68, 0, 83,112, 97, 99,101, 76,105,110,107, 0, 86,105,101,119, - 50, 68, 0, 83,112, 97, 99,101, 73,110,102,111, 0, 83,112, 97, 99,101, 73,112,111, 0, 98, 68,111,112,101, 83,104,101,101,116, - 0, 83,112, 97, 99,101, 66,117,116,115, 0, 83,112, 97, 99,101, 83,101,113, 0, 70,105,108,101, 83,101,108,101, 99,116, 80, 97, -114, 97,109,115, 0, 83,112, 97, 99,101, 70,105,108,101, 0, 70,105,108,101, 76,105,115,116, 0,119,109, 79,112,101,114, 97,116, -111,114, 0, 70,105,108,101, 76, 97,121,111,117,116, 0, 83,112, 97, 99,101, 79,111,112,115, 0, 84,114,101,101, 83,116,111,114, -101, 0, 84,114,101,101, 83,116,111,114,101, 69,108,101,109, 0, 83,112, 97, 99,101, 73,109, 97,103,101, 0, 83, 99,111,112,101, -115, 0, 72,105,115,116,111,103,114, 97,109, 0, 83,112, 97, 99,101, 78,108, 97, 0, 83,112, 97, 99,101, 84,101,120,116, 0, 83, - 99,114,105,112,116, 0, 83,112, 97, 99,101, 83, 99,114,105,112,116, 0, 83,112, 97, 99,101, 84,105,109,101, 67, 97, 99,104,101, - 0, 83,112, 97, 99,101, 84,105,109,101, 0, 83,112, 97, 99,101, 78,111,100,101, 0, 83,112, 97, 99,101, 76,111,103,105, 99, 0, - 67,111,110,115,111,108,101, 76,105,110,101, 0, 83,112, 97, 99,101, 67,111,110,115,111,108,101, 0, 83,112, 97, 99,101, 85,115, -101,114, 80,114,101,102, 0, 83,112, 97, 99,101, 67,108,105,112, 0, 77,111,118,105,101, 67,108,105,112, 83, 99,111,112,101,115, - 0,117,105, 70,111,110,116, 0,117,105, 70,111,110,116, 83,116,121,108,101, 0,117,105, 83,116,121,108,101, 0,117,105, 87,105, -100,103,101,116, 67,111,108,111,114,115, 0,117,105, 87,105,100,103,101,116, 83,116, 97,116,101, 67,111,108,111,114,115, 0,117, -105, 80, 97,110,101,108, 67,111,108,111,114,115, 0, 84,104,101,109,101, 85, 73, 0, 84,104,101,109,101, 83,112, 97, 99,101, 0, - 84,104,101,109,101, 87,105,114,101, 67,111,108,111,114, 0, 98, 84,104,101,109,101, 0, 98, 65,100,100,111,110, 0, 83,111,108, -105,100, 76,105,103,104,116, 0, 85,115,101,114, 68,101,102, 0, 98, 83, 99,114,101,101,110, 0, 83, 99,114, 86,101,114,116, 0, - 83, 99,114, 69,100,103,101, 0, 80, 97,110,101,108, 0, 80, 97,110,101,108, 84,121,112,101, 0,117,105, 76, 97,121,111,117,116, - 0, 83, 99,114, 65,114,101, 97, 0, 83,112, 97, 99,101, 84,121,112,101, 0, 65, 82,101,103,105,111,110, 0, 65, 82,101,103,105, -111,110, 84,121,112,101, 0, 70,105,108,101, 71,108,111, 98, 97,108, 0, 83,116,114,105,112, 69,108,101,109, 0, 83,116,114,105, -112, 67,114,111,112, 0, 83,116,114,105,112, 84,114, 97,110,115,102,111,114,109, 0, 83,116,114,105,112, 67,111,108,111,114, 66, - 97,108, 97,110, 99,101, 0, 83,116,114,105,112, 80,114,111,120,121, 0, 83,116,114,105,112, 0, 80,108,117,103,105,110, 83,101, -113, 0, 83,101,113,117,101,110, 99,101, 0, 98, 83,111,117,110,100, 0, 77,101,116, 97, 83,116, 97, 99,107, 0, 87,105,112,101, - 86, 97,114,115, 0, 71,108,111,119, 86, 97,114,115, 0, 84,114, 97,110,115,102,111,114,109, 86, 97,114,115, 0, 83,111,108,105, -100, 67,111,108,111,114, 86, 97,114,115, 0, 83,112,101,101,100, 67,111,110,116,114,111,108, 86, 97,114,115, 0, 69,102,102,101, - 99,116, 0, 66,117,105,108,100, 69,102,102, 0, 80, 97,114,116, 69,102,102, 0, 80, 97,114,116,105, 99,108,101, 0, 87, 97,118, -101, 69,102,102, 0, 98, 80,114,111,112,101,114,116,121, 0, 98, 78,101, 97,114, 83,101,110,115,111,114, 0, 98, 77,111,117,115, -101, 83,101,110,115,111,114, 0, 98, 84,111,117, 99,104, 83,101,110,115,111,114, 0, 98, 75,101,121, 98,111, 97,114,100, 83,101, -110,115,111,114, 0, 98, 80,114,111,112,101,114,116,121, 83,101,110,115,111,114, 0, 98, 65, 99,116,117, 97,116,111,114, 83,101, -110,115,111,114, 0, 98, 68,101,108, 97,121, 83,101,110,115,111,114, 0, 98, 67,111,108,108,105,115,105,111,110, 83,101,110,115, -111,114, 0, 98, 82, 97,100, 97,114, 83,101,110,115,111,114, 0, 98, 82, 97,110,100,111,109, 83,101,110,115,111,114, 0, 98, 82, - 97,121, 83,101,110,115,111,114, 0, 98, 65,114,109, 97,116,117,114,101, 83,101,110,115,111,114, 0, 98, 77,101,115,115, 97,103, -101, 83,101,110,115,111,114, 0, 98, 83,101,110,115,111,114, 0, 98, 67,111,110,116,114,111,108,108,101,114, 0, 98, 74,111,121, -115,116,105, 99,107, 83,101,110,115,111,114, 0, 98, 69,120,112,114,101,115,115,105,111,110, 67,111,110,116, 0, 98, 80,121,116, -104,111,110, 67,111,110,116, 0, 98, 65, 99,116,117, 97,116,111,114, 0, 98, 65,100,100, 79, 98,106,101, 99,116, 65, 99,116,117, - 97,116,111,114, 0, 98, 65, 99,116,105,111,110, 65, 99,116,117, 97,116,111,114, 0, 83,111,117,110,100, 51, 68, 0, 98, 83,111, -117,110,100, 65, 99,116,117, 97,116,111,114, 0, 98, 69,100,105,116, 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, - 98, 83, 99,101,110,101, 65, 99,116,117, 97,116,111,114, 0, 98, 80,114,111,112,101,114,116,121, 65, 99,116,117, 97,116,111,114, - 0, 98, 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 73,112,111, 65, 99,116,117, 97,116,111,114, 0, 98, 67, - 97,109,101,114, 97, 65, 99,116,117, 97,116,111,114, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 65, 99,116,117, 97,116,111, -114, 0, 98, 71,114,111,117,112, 65, 99,116,117, 97,116,111,114, 0, 98, 82, 97,110,100,111,109, 65, 99,116,117, 97,116,111,114, - 0, 98, 77,101,115,115, 97,103,101, 65, 99,116,117, 97,116,111,114, 0, 98, 71, 97,109,101, 65, 99,116,117, 97,116,111,114, 0, - 98, 86,105,115,105, 98,105,108,105,116,121, 65, 99,116,117, 97,116,111,114, 0, 98, 84,119,111, 68, 70,105,108,116,101,114, 65, - 99,116,117, 97,116,111,114, 0, 98, 80, 97,114,101,110,116, 65, 99,116,117, 97,116,111,114, 0, 98, 83,116, 97,116,101, 65, 99, -116,117, 97,116,111,114, 0, 98, 65,114,109, 97,116,117,114,101, 65, 99,116,117, 97,116,111,114, 0, 98, 83,116,101,101,114,105, -110,103, 65, 99,116,117, 97,116,111,114, 0, 71,114,111,117,112, 79, 98,106,101, 99,116, 0, 66,111,110,101, 0, 98, 65,114,109, - 97,116,117,114,101, 0, 98, 77,111,116,105,111,110, 80, 97,116,104, 86,101,114,116, 0, 98, 80,111,115,101, 67,104, 97,110,110, -101,108, 0, 98, 73, 75, 80, 97,114, 97,109, 0, 98, 73,116, 97,115, 99, 0, 98, 65, 99,116,105,111,110, 71,114,111,117,112, 0, - 83,112, 97, 99,101, 65, 99,116,105,111,110, 0, 98, 65, 99,116,105,111,110, 67,104, 97,110,110,101,108, 0, 98, 67,111,110,115, -116,114, 97,105,110,116, 67,104, 97,110,110,101,108, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 67,111,110,115,116, -114, 97,105,110,116, 84, 97,114,103,101,116, 0, 98, 80,121,116,104,111,110, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 75, -105,110,101,109, 97,116,105, 99, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,112,108,105,110,101, 73, 75, 67,111,110,115, -116,114, 97,105,110,116, 0, 98, 84,114, 97, 99,107, 84,111, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,111,116, 97,116, -101, 76,105,107,101, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 76,111, 99, 97,116,101, 76,105,107,101, 67,111,110,115,116, -114, 97,105,110,116, 0, 98, 83,105,122,101, 76,105,107,101, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83, 97,109,101, 86, -111,108,117,109,101, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 84,114, 97,110,115, 76,105,107,101, 67,111,110,115,116,114, - 97,105,110,116, 0, 98, 77,105,110, 77, 97,120, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 65, 99,116,105,111,110, 67,111, -110,115,116,114, 97,105,110,116, 0, 98, 76,111, 99,107, 84,114, 97, 99,107, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 68, - 97,109,112, 84,114, 97, 99,107, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 70,111,108,108,111,119, 80, 97,116,104, 67,111, -110,115,116,114, 97,105,110,116, 0, 98, 83,116,114,101,116, 99,104, 84,111, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82, -105,103,105,100, 66,111,100,121, 74,111,105,110,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 67,108, 97,109,112, 84,111, - 67,111,110,115,116,114, 97,105,110,116, 0, 98, 67,104,105,108,100, 79,102, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 84, -114, 97,110,115,102,111,114,109, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 80,105,118,111,116, 67,111,110,115,116,114, 97, -105,110,116, 0, 98, 76,111, 99, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,111,116, 76,105,109,105, -116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,105,122,101, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, - 0, 98, 68,105,115,116, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,104,114,105,110,107,119,114, 97, -112, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 70,111,108,108,111,119, 84,114, 97, 99,107, 67,111,110,115,116,114, 97,105, -110,116, 0, 98, 67, 97,109,101,114, 97, 83,111,108,118,101,114, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 79, 98,106,101, - 99,116, 83,111,108,118,101,114, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 65, 99,116,105,111,110, 77,111,100,105,102,105, -101,114, 0, 98, 65, 99,116,105,111,110, 83,116,114,105,112, 0, 98, 78,111,100,101, 83,116, 97, 99,107, 0, 98, 78,111,100,101, - 83,111, 99,107,101,116, 0, 98, 78,111,100,101, 76,105,110,107, 0, 98, 78,111,100,101, 80,114,101,118,105,101,119, 0, 98, 78, -111,100,101, 0,117,105, 66,108,111, 99,107, 0, 98, 78,111,100,101, 84,121,112,101, 0, 98, 78,111,100,101, 84,114,101,101, 69, -120,101, 99, 0, 98, 78,111,100,101, 83,111, 99,107,101,116, 86, 97,108,117,101, 73,110,116, 0, 98, 78,111,100,101, 83,111, 99, -107,101,116, 86, 97,108,117,101, 70,108,111, 97,116, 0, 98, 78,111,100,101, 83,111, 99,107,101,116, 86, 97,108,117,101, 66,111, -111,108,101, 97,110, 0, 98, 78,111,100,101, 83,111, 99,107,101,116, 86, 97,108,117,101, 86,101, 99,116,111,114, 0, 98, 78,111, -100,101, 83,111, 99,107,101,116, 86, 97,108,117,101, 82, 71, 66, 65, 0, 78,111,100,101, 73,109, 97,103,101, 65,110,105,109, 0, - 78,111,100,101, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 68, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 66, -105,108, 97,116,101,114, 97,108, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 72,117,101, 83, 97,116, 0, 78,111,100,101, - 73,109, 97,103,101, 70,105,108,101, 0, 78,111,100,101, 73,109, 97,103,101, 77,117,108,116,105, 70,105,108,101, 0, 78,111,100, -101, 73,109, 97,103,101, 77,117,108,116,105, 70,105,108,101, 83,111, 99,107,101,116, 0, 78,111,100,101, 67,104,114,111,109, 97, - 0, 78,111,100,101, 84,119,111, 88, 89,115, 0, 78,111,100,101, 84,119,111, 70,108,111, 97,116,115, 0, 78,111,100,101, 71,101, -111,109,101,116,114,121, 0, 78,111,100,101, 86,101,114,116,101,120, 67,111,108, 0, 78,111,100,101, 68,101,102,111, 99,117,115, - 0, 78,111,100,101, 83, 99,114,105,112,116, 68,105, 99,116, 0, 78,111,100,101, 71,108, 97,114,101, 0, 78,111,100,101, 84,111, -110,101,109, 97,112, 0, 78,111,100,101, 76,101,110,115, 68,105,115,116, 0, 78,111,100,101, 67,111,108,111,114, 66, 97,108, 97, -110, 99,101, 0, 78,111,100,101, 67,111,108,111,114,115,112,105,108,108, 0, 78,111,100,101, 84,101,120, 66, 97,115,101, 0, 78, -111,100,101, 84,101,120, 83,107,121, 0, 78,111,100,101, 84,101,120, 73,109, 97,103,101, 0, 78,111,100,101, 84,101,120, 67,104, -101, 99,107,101,114, 0, 78,111,100,101, 84,101,120, 69,110,118,105,114,111,110,109,101,110,116, 0, 78,111,100,101, 84,101,120, - 71,114, 97,100,105,101,110,116, 0, 78,111,100,101, 84,101,120, 78,111,105,115,101, 0, 78,111,100,101, 84,101,120, 86,111,114, -111,110,111,105, 0, 78,111,100,101, 84,101,120, 77,117,115,103,114, 97,118,101, 0, 78,111,100,101, 84,101,120, 87, 97,118,101, - 0, 78,111,100,101, 84,101,120, 77, 97,103,105, 99, 0, 78,111,100,101, 83,104, 97,100,101,114, 65,116,116,114,105, 98,117,116, -101, 0, 84,101,120, 78,111,100,101, 79,117,116,112,117,116, 0, 67,117,114,118,101, 77, 97,112, 80,111,105,110,116, 0, 67,117, -114,118,101, 77, 97,112, 0, 66,114,117,115,104, 67,108,111,110,101, 0, 67,117,115,116,111,109, 68, 97,116, 97, 76, 97,121,101, -114, 0, 67,117,115,116,111,109, 68, 97,116, 97, 69,120,116,101,114,110, 97,108, 0, 72, 97,105,114, 75,101,121, 0, 80, 97,114, -116,105, 99,108,101, 75,101,121, 0, 66,111,105,100, 80, 97,114,116,105, 99,108,101, 0, 66,111,105,100, 68, 97,116, 97, 0, 80, - 97,114,116,105, 99,108,101, 83,112,114,105,110,103, 0, 67,104,105,108,100, 80, 97,114,116,105, 99,108,101, 0, 80, 97,114,116, -105, 99,108,101, 84, 97,114,103,101,116, 0, 80, 97,114,116,105, 99,108,101, 68,117,112,108,105, 87,101,105,103,104,116, 0, 80, - 97,114,116,105, 99,108,101, 68, 97,116, 97, 0, 83, 80, 72, 70,108,117,105,100, 83,101,116,116,105,110,103,115, 0, 80, 97,114, -116,105, 99,108,101, 83,101,116,116,105,110,103,115, 0, 66,111,105,100, 83,101,116,116,105,110,103,115, 0, 80, 97,114,116,105, - 99,108,101, 67, 97, 99,104,101, 75,101,121, 0, 75, 68, 84,114,101,101, 0, 80, 97,114,116,105, 99,108,101, 68,114, 97,119, 68, - 97,116, 97, 0, 76,105,110,107, 78,111,100,101, 0, 98, 71, 80, 68,115,112,111,105,110,116, 0, 98, 71, 80, 68,115,116,114,111, -107,101, 0, 98, 71, 80, 68,102,114, 97,109,101, 0, 98, 71, 80, 68,108, 97,121,101,114, 0, 82,101,112,111,114,116, 76,105,115, -116, 0,119,109, 87,105,110,100,111,119, 77, 97,110, 97,103,101,114, 0,119,109, 87,105,110,100,111,119, 0,119,109, 75,101,121, - 67,111,110,102,105,103, 0,119,109, 69,118,101,110,116, 0,119,109, 83,117, 98, 87,105,110,100,111,119, 0,119,109, 71,101,115, -116,117,114,101, 0,119,109, 75,101,121, 77, 97,112, 73,116,101,109, 0, 80,111,105,110,116,101,114, 82, 78, 65, 0,119,109, 75, -101,121, 77, 97,112, 68,105,102,102, 73,116,101,109, 0,119,109, 75,101,121, 77, 97,112, 0,119,109, 79,112,101,114, 97,116,111, -114, 84,121,112,101, 0, 70, 77,111,100,105,102,105,101,114, 0, 70, 77,111,100, 95, 71,101,110,101,114, 97,116,111,114, 0, 70, - 77,111,100, 95, 70,117,110, 99,116,105,111,110, 71,101,110,101,114, 97,116,111,114, 0, 70, 67, 77, 95, 69,110,118,101,108,111, -112,101, 68, 97,116, 97, 0, 70, 77,111,100, 95, 69,110,118,101,108,111,112,101, 0, 70, 77,111,100, 95, 67,121, 99,108,101,115, - 0, 70, 77,111,100, 95, 80,121,116,104,111,110, 0, 70, 77,111,100, 95, 76,105,109,105,116,115, 0, 70, 77,111,100, 95, 78,111, -105,115,101, 0, 70, 77,111,100, 95, 83,116,101,112,112,101,100, 0, 68,114,105,118,101,114, 84, 97,114,103,101,116, 0, 68,114, -105,118,101,114, 86, 97,114, 0, 67,104, 97,110,110,101,108, 68,114,105,118,101,114, 0, 70, 80,111,105,110,116, 0, 70, 67,117, -114,118,101, 0, 65,110,105,109, 77, 97,112, 80, 97,105,114, 0, 65,110,105,109, 77, 97,112,112,101,114, 0, 78,108, 97, 83,116, -114,105,112, 0, 78,108, 97, 84,114, 97, 99,107, 0, 75, 83, 95, 80, 97,116,104, 0, 75,101,121,105,110,103, 83,101,116, 0, 65, -110,105,109, 79,118,101,114,114,105,100,101, 0, 73,100, 65,100,116, 84,101,109,112,108, 97,116,101, 0, 66,111,105,100, 82,117, -108,101, 0, 66,111,105,100, 82,117,108,101, 71,111, 97,108, 65,118,111,105,100, 0, 66,111,105,100, 82,117,108,101, 65,118,111, -105,100, 67,111,108,108,105,115,105,111,110, 0, 66,111,105,100, 82,117,108,101, 70,111,108,108,111,119, 76,101, 97,100,101,114, - 0, 66,111,105,100, 82,117,108,101, 65,118,101,114, 97,103,101, 83,112,101,101,100, 0, 66,111,105,100, 82,117,108,101, 70,105, -103,104,116, 0, 66,111,105,100, 83,116, 97,116,101, 0, 70, 76, 85, 73, 68, 95, 51, 68, 0, 87, 84, 85, 82, 66, 85, 76, 69, 78, - 67, 69, 0, 83,112,101, 97,107,101,114, 0, 77,111,118,105,101, 67,108,105,112, 80,114,111,120,121, 0, 77,111,118,105,101, 67, -108,105,112, 67, 97, 99,104,101, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, 0, 77,111,118,105,101, 84,114, 97, 99, -107,105,110,103, 84,114, 97, 99,107, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, 77, 97,114,107,101,114, 0, 77,111, -118,105,101, 82,101, 99,111,110,115,116,114,117, 99,116,101,100, 67, 97,109,101,114, 97, 0, 77,111,118,105,101, 84,114, 97, 99, -107,105,110,103, 67, 97,109,101,114, 97, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, 83,101,116,116,105,110,103,115, - 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, 83,116, 97, 98,105,108,105,122, 97,116,105,111,110, 0, 77,111,118,105, -101, 84,114, 97, 99,107,105,110,103, 82,101, 99,111,110,115,116,114,117, 99,116,105,111,110, 0, 77,111,118,105,101, 84,114, 97, - 99,107,105,110,103, 79, 98,106,101, 99,116, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, 83,116, 97,116,115, 0, 68, -121,110, 97,109,105, 99, 80, 97,105,110,116, 83,117,114,102, 97, 99,101, 0, 80, 97,105,110,116, 83,117,114,102, 97, 99,101, 68, - 97,116, 97, 0, 84, 76, 69, 78, 1, 0, 1, 0, 2, 0, 2, 0, 4, 0, 4, 0, 4, 0, 4, 0, 8, 0, 8, 0, 8, 0, 0, 0, - 16, 0, 24, 0, 16, 0, 4, 0, 8, 0, 12, 0, 16, 0, 16, 0, 32, 0,128, 0,120, 0,152, 8, 0, 0, 40, 0,144, 0,112, 5, -112, 0, 36, 0, 56, 0,160, 0,200, 0, 0, 1, 96, 0, 40, 0, 48, 0,224, 0, 16, 0,200, 0, 40, 0,216, 11, 48, 5, 0, 0, - 0, 0, 0, 0, 56, 1,168, 1,216, 4, 24, 0, 8, 3,200, 0, 0, 0,104, 0, 64, 1, 56, 4, 80, 0, 24, 1,144, 0, 56, 3, - 16, 2, 88, 0, 16, 0,128, 3,152, 0,136, 4, 0, 0,104, 0,104, 0, 0, 1, 80, 0, 8, 0, 16, 0, 32, 0, 0, 0, 8, 2, - 0, 0, 0, 0, 0, 0,232, 4, 12, 0, 16, 0, 8, 0, 12, 0, 4, 0, 20, 0, 48, 0, 64, 0, 20, 0, 12, 0, 16, 0, 4, 0, - 8, 0, 8, 0, 0, 0,176, 0,144, 1, 8, 0, 4, 0, 4, 0, 0, 1, 32, 0, 8, 0, 24, 0, 16, 0, 64, 0, 24, 0, 12, 0, - 64, 0, 4, 0,112, 0,200, 0,136, 0,192, 0,192, 0,128, 0,192, 0,192, 0,128, 0,120, 0,200, 0,120, 0,144, 0, 16, 1, - 56, 0,192, 0, 24, 1, 40, 1,120, 0,184, 0,200, 0, 64, 1,200, 0, 88, 1,112, 0,168, 0, 0, 0,152, 0, 48, 0, 40, 5, -192, 0, 0, 0,152, 0, 0, 0, 0, 0,128, 0, 8, 0, 8, 0,112, 1,144, 0,152, 2,136, 0,192, 0,120, 0,128, 0,224, 4, -208, 0,200, 0,112, 0,208, 0,144, 0, 16, 5, 0, 0, 0, 0, 48, 1,104, 1,160, 1,104, 1,136, 0,104, 0,112, 0,128, 0, - 16, 0, 96, 1, 88, 0, 0, 0,200, 0,216, 0,152, 0, 48, 0, 24, 0,120, 0,152, 0,216, 1, 0, 1,184, 0, 0, 0, 72, 0, - 32, 0,176, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 12, 0, 24, 2, 40, 0,184, 0,152, 0, 64, 0, 72, 0, 32, 0,120, 0, - 24, 0, 56, 9, 64, 0, 24, 0, 16, 0, 56, 0,168, 0, 96, 0, 24, 0, 88, 6, 48, 0, 16, 0,168, 0, 96, 0, 24, 0, 56, 0, -120, 0, 16, 0,232, 1, 32, 0, 8, 0, 24, 0, 80, 8, 0, 0, 0, 0,192, 8,104, 0, 8, 0,112, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 96, 1, 56, 0,144, 0, 64, 0,240, 0,112, 0,248, 0,240, 0,160, 7,104, 0, 0, 0,168, 0, 0, 0, 24, 1, - 16, 0, 16, 0, 40, 33,128, 16, 24, 16,216, 0,160, 2,168, 5, 64, 0, 24, 0,208, 0, 48, 1, 72, 0, 40, 0,136, 1,104, 0, - 40, 1, 56, 0, 24, 4, 32, 0,232, 0, 32, 0, 32, 0, 8, 0, 80, 3,224, 1, 16, 0,168, 36, 80, 0, 56, 0,112, 38, 8, 1, - 32, 0, 40, 0, 88, 1, 0, 0, 0, 0,160, 0, 0, 0, 40, 1, 0, 0, 48, 4, 8, 1, 16, 0, 8, 0, 44, 0, 16, 4, 72, 3, -200, 4, 72, 1,208, 4, 32, 0, 12, 0, 24, 0, 32, 0, 16, 0, 24, 0, 24, 0, 32, 0,136, 1, 0, 0, 64, 0, 96, 0, 80, 0, - 8, 0, 80, 0,136, 0,200, 0, 72, 0, 8, 0,136, 0, 76, 0, 72, 0,204, 0,136, 0,136, 0,128, 0,136, 0, 92, 0,128, 0, - 80, 0,112, 0, 16, 0,168, 0, 32, 0, 72, 0,120, 0, 24, 0,144, 0,112, 0,148, 0, 32, 0,128, 0, 88, 0, 88, 0,208, 0, -140, 0, 4, 0, 24, 0, 16, 0, 8, 0,160, 0, 48, 0, 40, 0, 72, 1, 0, 1, 16, 0, 32, 2, 4, 0, 40, 0,120, 0, 72, 1, -120, 0, 56, 0,120, 0,160, 0,112, 0,184, 0, 24, 0, 88, 0, 80, 0, 80, 0, 80, 0, 8, 0, 72, 0,104, 0,104, 0, 80, 0, - 80, 0, 24, 0, 88, 0,104, 0, 16, 0,144, 0,128, 0, 88, 0, 28, 0, 28, 0, 28, 0, 88, 0, 24, 0,160, 0, 16, 0,152, 0, - 72, 0,168, 0, 48, 0,208, 0, 56, 0, 16, 0, 88, 1, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 4, 0, 24, 0, 16, 0, 16, 0, - 40, 0, 28, 0, 12, 0, 12, 0, 32, 4, 40, 4, 32, 0, 44, 0, 24, 0, 8, 0,128, 0, 64, 0, 32, 0, 16, 0, 32, 0, 32, 0, - 8, 0, 96, 0, 20, 0,200, 3,216, 3,208, 3,200, 3,208, 3,208, 3,200, 3,208, 3,208, 3,208, 3,208, 3, 64, 0, 64, 0, - 12, 0, 56, 0, 24, 0,104, 0, 0, 4, 24, 0, 56, 0, 56, 0, 20, 0, 16, 0, 64, 0, 40, 0, 32, 0,192, 0, 60, 0, 16, 3, -104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 32, 0, 40, 0,192, 0, 40, 0, 88, 1, 0, 1,168, 0, 0, 0, 0, 0, 0, 0, -120, 0, 0, 0, 32, 0,136, 0, 0, 0,120, 0, 24, 0, 24, 0, 16, 0, 24, 0, 8, 0, 16, 0, 24, 0, 20, 0, 20, 0, 56, 0, - 24, 2, 40, 1, 16, 0,104, 0, 0, 1, 40, 0,208, 0,104, 0,112, 0,216, 1, 32, 0,128, 0, 56, 0, 80, 0, 64, 0,104, 0, - 72, 0, 64, 0,128, 0, 0, 0, 0, 0,184, 0, 8, 3, 0, 0,248, 0,192, 0, 16, 0, 72, 0, 48, 0, 64, 0, 56, 0, 24, 0, -128, 0, 0, 1, 16, 6, 0, 0, 83, 84, 82, 67,207, 1, 0, 0, 12, 0, 2, 0, 12, 0, 0, 0, 12, 0, 1, 0, 13, 0, 3, 0, - 13, 0, 0, 0, 13, 0, 1, 0, 11, 0, 2, 0, 14, 0, 2, 0, 11, 0, 3, 0, 11, 0, 4, 0, 15, 0, 2, 0, 2, 0, 5, 0, - 2, 0, 6, 0, 16, 0, 2, 0, 7, 0, 5, 0, 7, 0, 6, 0, 17, 0, 3, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, - 18, 0, 4, 0, 4, 0, 8, 0, 4, 0, 9, 0, 4, 0, 10, 0, 4, 0, 11, 0, 19, 0, 4, 0, 7, 0, 8, 0, 7, 0, 9, 0, - 7, 0, 10, 0, 7, 0, 11, 0, 20, 0, 4, 0, 11, 0, 12, 0, 14, 0, 13, 0, 4, 0, 14, 0, 4, 0, 15, 0, 21, 0, 10, 0, - 21, 0, 0, 0, 21, 0, 1, 0, 0, 0, 16, 0, 0, 0, 17, 0, 2, 0, 18, 0, 0, 0, 19, 0, 4, 0, 20, 0, 20, 0, 21, 0, - 4, 0, 22, 0, 4, 0, 23, 0, 22, 0, 11, 0, 11, 0, 0, 0, 11, 0, 1, 0, 22, 0, 24, 0, 23, 0, 25, 0, 0, 0, 26, 0, - 2, 0, 27, 0, 2, 0, 28, 0, 2, 0, 18, 0, 4, 0, 29, 0, 4, 0, 30, 0, 21, 0, 31, 0, 23, 0, 8, 0, 22, 0, 32, 0, - 22, 0, 33, 0, 24, 0, 34, 0, 0, 0, 35, 0, 0, 0, 36, 0, 4, 0, 37, 0, 4, 0, 27, 0, 23, 0, 38, 0, 25, 0, 5, 0, - 4, 0, 39, 0, 4, 0, 40, 0, 2, 0, 41, 0, 2, 0, 42, 0, 4, 0, 43, 0, 26, 0, 6, 0, 27, 0, 44, 0, 2, 0, 45, 0, - 2, 0, 46, 0, 2, 0, 16, 0, 2, 0, 18, 0, 0, 0, 47, 0, 28, 0, 21, 0, 28, 0, 0, 0, 28, 0, 1, 0, 29, 0, 48, 0, - 30, 0, 49, 0, 19, 0, 50, 0, 19, 0, 51, 0, 2, 0, 45, 0, 2, 0, 46, 0, 2, 0, 52, 0, 2, 0, 53, 0, 2, 0, 54, 0, - 2, 0, 55, 0, 2, 0, 18, 0, 2, 0, 56, 0, 7, 0, 10, 0, 7, 0, 11, 0, 4, 0, 57, 0, 7, 0, 58, 0, 7, 0, 59, 0, - 7, 0, 60, 0, 26, 0, 61, 0, 31, 0, 7, 0, 22, 0, 32, 0, 14, 0, 62, 0, 19, 0, 63, 0, 2, 0, 45, 0, 2, 0, 64, 0, - 2, 0, 65, 0, 2, 0, 27, 0, 32, 0, 18, 0, 32, 0, 0, 0, 32, 0, 1, 0, 7, 0, 66, 0, 7, 0, 60, 0, 2, 0, 16, 0, - 2, 0, 46, 0, 2, 0, 67, 0, 2, 0, 18, 0, 4, 0, 68, 0, 4, 0, 30, 0, 11, 0, 2, 0, 7, 0, 69, 0, 0, 0, 19, 0, - 0, 0, 70, 0, 7, 0, 71, 0, 7, 0, 72, 0, 4, 0, 73, 0, 4, 0, 74, 0, 33, 0, 15, 0, 22, 0, 32, 0, 34, 0, 75, 0, - 32, 0, 76, 0, 0, 0, 77, 0, 4, 0, 78, 0, 7, 0, 60, 0, 14, 0, 79, 0, 31, 0, 80, 0, 22, 0, 81, 0, 2, 0, 16, 0, - 2, 0, 82, 0, 2, 0, 83, 0, 2, 0, 18, 0, 4, 0, 84, 0, 4, 0, 27, 0, 35, 0, 6, 0, 35, 0, 0, 0, 35, 0, 1, 0, - 0, 0, 85, 0, 0, 0, 86, 0, 4, 0, 22, 0, 4, 0, 87, 0, 36, 0, 10, 0, 36, 0, 0, 0, 36, 0, 1, 0, 4, 0, 88, 0, - 4, 0, 89, 0, 4, 0, 90, 0, 4, 0, 91, 0, 4, 0, 13, 0, 4, 0, 92, 0, 0, 0, 93, 0, 0, 0, 94, 0, 37, 0, 15, 0, - 22, 0, 32, 0, 0, 0, 95, 0, 4, 0, 92, 0, 4, 0, 96, 0, 14, 0, 97, 0, 35, 0, 98, 0, 35, 0, 99, 0, 4, 0,100, 0, - 4, 0,101, 0, 14, 0,102, 0, 0, 0,103, 0, 4, 0,104, 0, 4, 0,105, 0, 11, 0,106, 0, 8, 0,107, 0, 38, 0, 3, 0, - 4, 0,108, 0, 4, 0,109, 0, 11, 0, 2, 0, 39, 0, 20, 0, 22, 0, 32, 0, 34, 0, 75, 0, 0, 0, 16, 0, 0, 0,110, 0, - 2, 0, 18, 0, 7, 0,111, 0, 7, 0,112, 0, 7, 0,113, 0, 7, 0,114, 0, 7, 0,115, 0, 7, 0,116, 0, 7, 0,117, 0, - 7, 0,118, 0, 7, 0,119, 0, 7, 0,120, 0, 7, 0,121, 0, 31, 0, 80, 0, 27, 0,122, 0, 0, 0,123, 0, 0, 0,124, 0, - 40, 0, 14, 0, 41, 0,125, 0, 4, 0,126, 0, 4, 0,127, 0, 4, 0,128, 0, 4, 0,129, 0, 0, 0,130, 0, 0, 0,131, 0, - 0, 0,132, 0, 0, 0, 27, 0, 2, 0,133, 0, 2, 0,134, 0, 2, 0,135, 0, 2, 0, 18, 0, 4, 0, 30, 0, 42, 0, 33, 0, - 22, 0, 32, 0, 0, 0, 35, 0, 14, 0,136, 0, 43, 0,137, 0, 44, 0,138, 0, 45, 0,139, 0, 45, 0,140, 0, 2, 0,141, 0, - 2, 0,142, 0, 2, 0,132, 0, 2, 0, 18, 0, 2, 0,143, 0, 2, 0, 16, 0, 4, 0,144, 0, 2, 0,145, 0, 2, 0,146, 0, - 2, 0,147, 0, 2, 0,148, 0, 2, 0,149, 0, 2, 0,150, 0, 4, 0,151, 0, 4, 0,152, 0, 38, 0,153, 0, 25, 0,154, 0, - 7, 0,155, 0, 4, 0,156, 0, 2, 0,157, 0, 2, 0,158, 0, 2, 0,159, 0, 0, 0,160, 0, 0, 0,161, 0, 7, 0,162, 0, - 7, 0,163, 0, 46, 0, 65, 0, 2, 0,164, 0, 2, 0,165, 0, 2, 0,166, 0, 2, 0,167, 0, 27, 0,168, 0, 47, 0,169, 0, - 0, 0,170, 0, 0, 0,171, 0, 0, 0,172, 0, 0, 0,173, 0, 0, 0,174, 0, 7, 0,175, 0, 7, 0,176, 0, 7, 0,177, 0, - 2, 0,178, 0, 2, 0,179, 0, 2, 0,180, 0, 2, 0,181, 0, 2, 0,182, 0, 2, 0,183, 0, 0, 0,184, 0, 0, 0,124, 0, - 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0, 7, 0,188, 0, 7, 0,189, 0, 7, 0, 56, 0, 7, 0,190, 0, 7, 0,191, 0, - 7, 0,192, 0, 7, 0,193, 0, 7, 0,194, 0, 7, 0,195, 0, 7, 0,196, 0, 7, 0,197, 0, 7, 0,198, 0, 7, 0,199, 0, - 7, 0,200, 0, 7, 0,201, 0, 7, 0,202, 0, 7, 0,203, 0, 7, 0,204, 0, 7, 0,205, 0, 7, 0,206, 0, 7, 0,207, 0, - 7, 0,208, 0, 7, 0,209, 0, 7, 0,210, 0, 7, 0,211, 0, 7, 0,212, 0, 7, 0,213, 0, 7, 0,214, 0, 7, 0,215, 0, - 7, 0,216, 0, 7, 0,217, 0, 7, 0,218, 0, 7, 0,219, 0, 7, 0,220, 0, 7, 0,221, 0, 7, 0,222, 0, 7, 0,223, 0, - 7, 0,224, 0, 7, 0,225, 0, 7, 0,226, 0, 48, 0, 15, 0, 0, 0, 35, 0, 11, 0,227, 0, 0, 0,228, 0, 0, 0,229, 0, - 4, 0,230, 0, 4, 0,231, 0, 11, 0,232, 0, 7, 0,233, 0, 7, 0,234, 0, 7, 0,235, 0, 4, 0,236, 0, 11, 0,237, 0, - 11, 0,238, 0, 4, 0,239, 0, 4, 0, 27, 0, 49, 0, 6, 0, 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0, 7, 0,240, 0, - 7, 0, 66, 0, 4, 0, 63, 0, 50, 0, 5, 0, 2, 0, 18, 0, 2, 0, 37, 0, 2, 0, 63, 0, 2, 0,241, 0, 49, 0,235, 0, - 51, 0, 17, 0, 27, 0,168, 0, 42, 0,242, 0, 52, 0,243, 0, 7, 0,244, 0, 7, 0,245, 0, 2, 0, 16, 0, 2, 0,246, 0, - 7, 0,112, 0, 7, 0,113, 0, 7, 0,247, 0, 4, 0,248, 0, 2, 0,249, 0, 2, 0,250, 0, 4, 0,132, 0, 4, 0,144, 0, - 2, 0,251, 0, 2, 0,252, 0, 53, 0, 25, 0, 2, 0, 18, 0, 2, 0,253, 0, 7, 0,254, 0, 7, 0,255, 0, 2, 0,143, 0, - 2, 0, 0, 1, 4, 0, 1, 1, 4, 0, 2, 1, 27, 0,168, 0, 4, 0, 3, 1, 2, 0, 4, 1, 2, 0, 5, 1, 11, 0, 6, 1, - 7, 0, 7, 1, 7, 0, 8, 1, 2, 0, 9, 1, 2, 0, 10, 1, 2, 0, 11, 1, 2, 0, 12, 1, 7, 0, 13, 1, 7, 0, 14, 1, - 7, 0, 15, 1, 7, 0, 16, 1, 50, 0, 17, 1, 54, 0, 18, 1, 55, 0, 13, 0, 4, 0, 19, 1, 4, 0, 20, 1, 2, 0, 21, 1, - 2, 0, 18, 0, 2, 0, 22, 1, 2, 0, 23, 1, 27, 0,168, 0, 7, 0, 24, 1, 4, 0, 25, 1, 0, 0, 26, 1, 7, 0, 27, 1, - 4, 0, 28, 1, 4, 0,132, 0, 56, 0, 4, 0, 27, 0,168, 0, 0, 0, 29, 1, 4, 0, 30, 1, 4, 0, 27, 0, 47, 0, 64, 0, - 22, 0, 32, 0, 34, 0, 75, 0, 7, 0, 31, 1, 7, 0, 32, 1, 7, 0, 33, 1, 7, 0, 34, 1, 7, 0, 35, 1, 7, 0, 36, 1, - 7, 0, 37, 1, 7, 0, 38, 1, 7, 0, 39, 1, 7, 0, 30, 0, 7, 0, 40, 1, 7, 0, 41, 1, 7, 0, 42, 1, 7, 0, 43, 1, - 7, 0, 44, 1, 7, 0, 45, 1, 7, 0, 46, 1, 7, 0, 47, 1, 7, 0, 48, 1, 7, 0, 49, 1, 7, 0, 50, 1, 7, 0, 51, 1, - 2, 0, 52, 1, 2, 0, 53, 1, 2, 0, 54, 1, 2, 0, 55, 1, 2, 0, 56, 1, 2, 0, 57, 1, 2, 0, 58, 1, 2, 0, 18, 0, - 2, 0, 16, 0, 2, 0,246, 0, 7, 0, 59, 1, 7, 0, 60, 1, 7, 0, 61, 1, 7, 0, 62, 1, 4, 0, 63, 1, 4, 0, 64, 1, - 2, 0, 65, 1, 2, 0, 66, 1, 2, 0, 22, 1, 2, 0,130, 0, 4, 0, 22, 0, 4, 0,127, 0, 4, 0,128, 0, 4, 0,129, 0, - 7, 0, 67, 1, 7, 0, 68, 1, 7, 0, 91, 0, 40, 0, 69, 1, 57, 0, 70, 1, 31, 0, 80, 0, 42, 0,242, 0, 48, 0, 71, 1, - 50, 0, 17, 1, 51, 0, 72, 1, 25, 0,154, 0, 53, 0, 73, 1, 55, 0, 74, 1, 56, 0, 75, 1, 0, 0, 76, 1, 0, 0,124, 0, - 58, 0, 13, 0, 7, 0, 77, 1, 7, 0, 78, 1, 7, 0,176, 0, 4, 0, 18, 0, 0, 0,171, 0, 0, 0,172, 0, 0, 0,173, 0, - 0, 0,174, 0, 4, 0, 27, 0, 7, 0, 79, 1, 7, 0, 80, 1, 7, 0, 81, 1, 27, 0, 44, 0, 59, 0, 9, 0, 50, 0, 82, 1, - 7, 0, 33, 1, 7, 0, 34, 1, 7, 0, 35, 1, 4, 0, 18, 0, 7, 0, 83, 1, 7, 0, 84, 1, 4, 0, 85, 1, 4, 0, 86, 1, - 60, 0, 74, 0, 22, 0, 32, 0, 34, 0, 75, 0, 2, 0, 16, 0, 2, 0, 18, 0, 4, 0, 87, 1, 2, 0,179, 0, 2, 0, 88, 1, - 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0, 7, 0,188, 0, 7, 0, 89, 1, 7, 0, 90, 1, 7, 0, 91, 1, 7, 0, 92, 1, - 7, 0, 93, 1, 7, 0, 94, 1, 7, 0, 95, 1, 7, 0, 96, 1, 7, 0, 97, 1, 7, 0, 98, 1, 7, 0, 99, 1, 54, 0,100, 1, - 2, 0,253, 0, 2, 0, 30, 0, 7, 0,112, 0, 7, 0,113, 0, 7, 0,101, 1, 7, 0,102, 1, 7, 0,103, 1, 7, 0,104, 1, - 7, 0,105, 1, 2, 0,106, 1, 2, 0,107, 1, 2, 0,108, 1, 2, 0,109, 1, 0, 0,110, 1, 0, 0,111, 1, 2, 0,112, 1, - 2, 0,113, 1, 2, 0,114, 1, 2, 0,115, 1, 2, 0,116, 1, 7, 0,117, 1, 7, 0,118, 1, 7, 0,119, 1, 7, 0,120, 1, - 2, 0,121, 1, 2, 0, 91, 0, 2, 0,122, 1, 2, 0,123, 1, 2, 0,124, 1, 2, 0,125, 1, 7, 0,126, 1, 7, 0,127, 1, - 7, 0,128, 1, 7, 0,129, 1, 7, 0,130, 1, 7, 0,131, 1, 7, 0,132, 1, 7, 0,133, 1, 7, 0,134, 1, 7, 0,135, 1, - 7, 0,136, 1, 7, 0,137, 1, 2, 0,138, 1, 0, 0,139, 1, 31, 0, 80, 0, 46, 0,140, 1, 2, 0,141, 1, 2, 0, 76, 1, - 0, 0,142, 1, 25, 0,154, 0, 57, 0, 70, 1, 61, 0, 18, 0, 7, 0,143, 1, 7, 0,144, 1, 7, 0,145, 1, 7, 0,146, 1, - 7, 0,147, 1, 7, 0,148, 1, 7, 0,149, 1, 7, 0,150, 1, 7, 0,151, 1, 7, 0,152, 1, 2, 0,153, 1, 2, 0,154, 1, - 2, 0,155, 1, 2, 0,156, 1, 7, 0,157, 1, 7, 0,158, 1, 7, 0,159, 1, 7, 0,160, 1, 62, 0, 4, 0, 4, 0, 18, 0, - 4, 0,161, 1, 4, 0,162, 1, 4, 0, 91, 0, 63, 0,126, 0, 22, 0, 32, 0, 34, 0, 75, 0, 2, 0,163, 1, 2, 0, 18, 0, - 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0, 7, 0,164, 1, 7, 0,165, 1, 7, 0,166, 1, 7, 0,167, 1, 7, 0,168, 1, - 7, 0,169, 1, 7, 0,170, 1, 7, 0,171, 1, 7, 0,172, 1, 7, 0,173, 1, 7, 0,174, 1, 7, 0,175, 1, 7, 0,176, 1, - 7, 0,177, 1, 7, 0,178, 1, 7, 0,179, 1, 7, 0,180, 1, 7, 0,181, 1, 7, 0,182, 1, 7, 0,183, 1, 61, 0,184, 1, - 62, 0,185, 1, 7, 0,186, 1, 7, 0,187, 1, 7, 0,188, 1, 7, 0,189, 1, 7, 0,190, 1, 7, 0,191, 1, 7, 0,192, 1, - 2, 0,193, 1, 2, 0,194, 1, 2, 0,195, 1, 0, 0,196, 1, 0, 0,197, 1, 7, 0,198, 1, 7, 0,199, 1, 2, 0,200, 1, - 2, 0,201, 1, 7, 0,202, 1, 7, 0,203, 1, 7, 0,204, 1, 7, 0,205, 1, 2, 0,206, 1, 2, 0,207, 1, 4, 0, 87, 1, - 4, 0,208, 1, 2, 0,209, 1, 2, 0,210, 1, 2, 0,211, 1, 2, 0,212, 1, 7, 0,213, 1, 7, 0,214, 1, 7, 0,215, 1, - 7, 0,216, 1, 7, 0,217, 1, 7, 0,218, 1, 7, 0,219, 1, 7, 0,220, 1, 7, 0,221, 1, 7, 0,222, 1, 0, 0,223, 1, - 7, 0,224, 1, 7, 0,225, 1, 7, 0,226, 1, 4, 0,227, 1, 0, 0,228, 1, 0, 0,122, 1, 0, 0,229, 1, 0, 0, 76, 1, - 2, 0,230, 1, 2, 0,231, 1, 2, 0,141, 1, 2, 0,232, 1, 2, 0,233, 1, 2, 0,234, 1, 7, 0,235, 1, 7, 0,236, 1, - 7, 0,237, 1, 7, 0,238, 1, 7, 0,239, 1, 2, 0,164, 0, 2, 0,165, 0, 50, 0,240, 1, 50, 0,241, 1, 0, 0,242, 1, - 0, 0,243, 1, 0, 0,244, 1, 0, 0,245, 1, 2, 0,246, 1, 2, 0, 74, 0, 7, 0,247, 1, 7, 0,248, 1, 46, 0,140, 1, - 57, 0, 70, 1, 31, 0, 80, 0, 64, 0,249, 1, 25, 0,154, 0, 7, 0,250, 1, 7, 0,251, 1, 7, 0,252, 1, 7, 0,253, 1, - 7, 0,254, 1, 2, 0,255, 1, 2, 0, 30, 0, 7, 0, 0, 2, 7, 0, 1, 2, 7, 0, 2, 2, 7, 0, 3, 2, 7, 0, 4, 2, - 7, 0, 5, 2, 7, 0, 6, 2, 7, 0, 7, 2, 7, 0, 8, 2, 2, 0, 9, 2, 2, 0, 10, 2, 4, 0, 11, 2, 2, 0, 12, 2, - 2, 0, 13, 2, 14, 0, 14, 2, 65, 0, 4, 0, 22, 0, 32, 0, 0, 0, 35, 0, 66, 0, 2, 0, 38, 0,153, 0, 67, 0, 20, 0, - 67, 0, 0, 0, 67, 0, 1, 0, 68, 0, 15, 2, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 16, 2, 2, 0, 17, 2, 7, 0, 5, 0, - 7, 0, 6, 0, 7, 0, 7, 0, 7, 0, 18, 2, 7, 0, 19, 2, 7, 0, 20, 2, 7, 0, 21, 2, 7, 0, 22, 2, 7, 0, 23, 2, - 7, 0, 24, 2, 7, 0, 22, 0, 7, 0, 25, 2, 7, 0, 26, 2, 69, 0, 20, 0, 22, 0, 32, 0, 34, 0, 75, 0, 68, 0, 15, 2, - 14, 0, 27, 2, 14, 0, 28, 2, 14, 0, 29, 2, 31, 0, 80, 0, 63, 0, 30, 2, 0, 0, 18, 0, 0, 0, 31, 2, 2, 0, 32, 2, - 2, 0,178, 0, 2, 0, 27, 0, 7, 0, 77, 1, 7, 0,176, 0, 7, 0, 78, 1, 7, 0, 33, 2, 7, 0, 34, 2, 7, 0, 35, 2, - 67, 0, 36, 2, 30, 0, 11, 0, 7, 0, 37, 2, 7, 0, 38, 2, 7, 0, 39, 2, 7, 0,255, 0, 2, 0, 54, 0, 0, 0, 40, 2, - 0, 0, 41, 2, 0, 0, 42, 2, 0, 0, 43, 2, 0, 0, 44, 2, 0, 0, 45, 2, 29, 0, 7, 0, 7, 0, 46, 2, 7, 0, 38, 2, - 7, 0, 39, 2, 2, 0, 42, 2, 2, 0, 45, 2, 7, 0,255, 0, 7, 0, 27, 0, 70, 0, 21, 0, 70, 0, 0, 0, 70, 0, 1, 0, - 2, 0, 16, 0, 2, 0, 47, 2, 2, 0, 45, 2, 2, 0, 18, 0, 2, 0, 48, 2, 2, 0, 49, 2, 2, 0, 50, 2, 2, 0, 51, 2, - 2, 0, 52, 2, 2, 0, 53, 2, 2, 0, 54, 2, 2, 0, 55, 2, 7, 0, 56, 2, 7, 0, 57, 2, 29, 0, 48, 0, 30, 0, 49, 0, - 2, 0, 58, 2, 2, 0, 59, 2, 4, 0, 60, 2, 71, 0, 5, 0, 2, 0, 61, 2, 2, 0, 47, 2, 0, 0, 18, 0, 0, 0, 27, 0, - 2, 0, 30, 0, 72, 0, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 62, 2, 7, 0, 63, 2, 73, 0, 4, 0, 14, 0, 64, 2, - 74, 0, 65, 2, 4, 0, 66, 2, 0, 0, 94, 0, 75, 0, 68, 0, 22, 0, 32, 0, 34, 0, 75, 0, 68, 0, 15, 2, 14, 0, 67, 2, - 14, 0, 28, 2, 73, 0, 68, 2, 27, 0, 69, 2, 27, 0, 70, 2, 27, 0, 71, 2, 31, 0, 80, 0, 76, 0, 72, 2, 33, 0, 73, 2, - 63, 0, 30, 2, 14, 0, 74, 2, 7, 0, 77, 1, 7, 0,176, 0, 7, 0, 78, 1, 2, 0, 16, 0, 2, 0,178, 0, 2, 0, 75, 2, - 2, 0, 76, 2, 7, 0, 77, 2, 7, 0, 78, 2, 4, 0, 79, 2, 2, 0, 27, 0, 2, 0, 32, 2, 2, 0, 18, 0, 2, 0, 80, 2, - 7, 0, 81, 2, 7, 0, 82, 2, 7, 0, 83, 2, 2, 0, 50, 2, 2, 0, 51, 2, 2, 0, 84, 2, 2, 0, 85, 2, 4, 0, 86, 2, - 11, 0, 87, 2, 2, 0, 22, 0, 2, 0, 97, 0, 2, 0, 66, 0, 2, 0, 88, 2, 7, 0, 89, 2, 7, 0, 90, 2, 7, 0, 91, 2, - 7, 0, 92, 2, 7, 0, 93, 2, 7, 0, 94, 2, 7, 0, 95, 2, 7, 0, 96, 2, 7, 0, 97, 2, 7, 0, 98, 2, 0, 0, 99, 2, - 77, 0,100, 2, 78, 0,101, 2, 0, 0,102, 2, 65, 0,103, 2, 65, 0,104, 2, 65, 0,105, 2, 65, 0,106, 2, 4, 0,107, 2, - 7, 0,108, 2, 4, 0,109, 2, 4, 0,110, 2, 72, 0,111, 2, 4, 0,112, 2, 4, 0,113, 2, 71, 0,114, 2, 71, 0,115, 2, - 79, 0, 47, 0, 22, 0, 32, 0, 34, 0, 75, 0, 68, 0, 15, 2, 31, 0, 80, 0, 33, 0, 73, 2, 63, 0, 30, 2, 80, 0,116, 2, - 81, 0,117, 2, 82, 0,118, 2, 83, 0,119, 2, 84, 0,120, 2, 85, 0,121, 2, 86, 0,122, 2, 87, 0,123, 2, 88, 0,124, 2, - 89, 0,125, 2, 90, 0,126, 2, 91, 0,127, 2, 92, 0,128, 2, 79, 0,129, 2, 93, 0,130, 2, 94, 0,131, 2, 95, 0,132, 2, - 95, 0,133, 2, 95, 0,134, 2, 95, 0,135, 2, 95, 0,136, 2, 4, 0, 53, 0, 4, 0,137, 2, 4, 0,138, 2, 4, 0,139, 2, - 4, 0,140, 2, 4, 0,141, 2, 4, 0,142, 2, 7, 0, 77, 1, 7, 0,176, 0, 7, 0, 78, 1, 2, 0,178, 0, 2, 0, 75, 2, - 2, 0,143, 2, 2, 0, 18, 0, 2, 0,144, 2, 2, 0,145, 2, 0, 0,146, 2, 0, 0,147, 2, 2, 0, 32, 2, 96, 0,148, 2, - 87, 0, 8, 0, 11, 0,149, 2, 7, 0,150, 2, 4, 0,151, 2, 0, 0, 18, 0, 0, 0,152, 2, 2, 0, 87, 1, 2, 0,153, 2, - 2, 0,154, 2, 85, 0, 7, 0, 4, 0,155, 2, 4, 0,156, 2, 4, 0,157, 2, 4, 0,158, 2, 2, 0, 47, 2, 0, 0,159, 2, - 0, 0, 18, 0, 89, 0, 5, 0, 4, 0,155, 2, 4, 0,156, 2, 0, 0,160, 2, 0, 0,161, 2, 2, 0, 18, 0, 97, 0, 2, 0, - 4, 0,162, 2, 7, 0, 39, 2, 90, 0, 3, 0, 97, 0,163, 2, 4, 0,164, 2, 4, 0, 18, 0, 88, 0, 4, 0, 7, 0,165, 2, - 2, 0,166, 2, 0, 0, 18, 0, 0, 0,161, 2, 91, 0, 4, 0, 0, 0,240, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0,187, 0, - 80, 0, 5, 0, 4, 0,167, 2, 4, 0,141, 2, 2, 0, 47, 2, 0, 0, 18, 0, 0, 0, 27, 0, 82, 0, 2, 0, 4, 0,168, 2, - 4, 0,169, 2, 81, 0, 6, 0, 42, 0,149, 2, 0, 0, 18, 0, 0, 0,152, 2, 2, 0, 87, 1, 2, 0,153, 2, 2, 0,154, 2, - 83, 0, 2, 0, 7, 0,170, 2, 4, 0, 18, 0, 84, 0, 4, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0,187, 0, 0, 0,240, 0, - 92, 0, 1, 0, 7, 0,171, 2, 93, 0, 2, 0, 4, 0, 13, 2, 4, 0, 16, 0, 86, 0, 7, 0, 7, 0,150, 2, 42, 0,149, 2, - 0, 0, 18, 0, 0, 0,152, 2, 2, 0, 87, 1, 2, 0,153, 2, 2, 0,154, 2, 98, 0, 1, 0, 7, 0,172, 2, 99, 0, 1, 0, - 4, 0,173, 2,100, 0, 1, 0, 0, 0,174, 2,101, 0, 1, 0, 7, 0,150, 2,102, 0, 1, 0, 7, 0,170, 2,103, 0, 4, 0, - 4, 0,175, 2, 4, 0,176, 2, 7, 0,177, 2, 4, 0,178, 2,104, 0, 4, 0, 7, 0,240, 0, 7, 0,185, 0, 7, 0,186, 0, - 7, 0,187, 0,105, 0, 1, 0,104, 0,151, 2,106, 0, 5, 0, 4, 0,179, 2, 4, 0,180, 2, 0, 0, 18, 0, 0, 0, 47, 2, - 0, 0,181, 2,107, 0, 2, 0, 4, 0,182, 2, 4, 0,180, 2,108, 0, 10, 0,108, 0, 0, 0,108, 0, 1, 0,106, 0,183, 2, -105, 0,184, 2,107, 0,185, 2, 4, 0, 53, 0, 4, 0,138, 2, 4, 0,137, 2, 4, 0, 27, 0, 88, 0,186, 2, 96, 0, 14, 0, - 14, 0,187, 2, 88, 0,186, 2, 0, 0,188, 2, 0, 0,189, 2, 0, 0,190, 2, 0, 0,191, 2, 0, 0,192, 2, 0, 0,193, 2, - 0, 0,194, 2, 0, 0, 18, 0, 95, 0,132, 2, 95, 0,134, 2, 2, 0,195, 2, 0, 0,196, 2,109, 0, 1, 0, 4, 0,173, 2, -110, 0, 9, 0,110, 0, 0, 0,110, 0, 1, 0, 4, 0, 16, 0, 4, 0, 87, 1, 4, 0,197, 2, 4, 0, 27, 0, 0, 0, 19, 0, - 41, 0,125, 0, 0, 0,198, 2,111, 0, 6, 0,110, 0,199, 2, 47, 0,200, 2, 27, 0,201, 2, 0, 0,202, 2, 4, 0,203, 2, - 4, 0,204, 2,112, 0, 7, 0,110, 0,199, 2, 2, 0,205, 2, 2, 0,187, 2, 2, 0,206, 2, 2, 0, 92, 0, 11, 0,207, 2, - 11, 0,208, 2,113, 0, 5, 0,110, 0,199, 2, 27, 0,168, 0, 0, 0, 19, 0, 7, 0,209, 2, 0, 0, 94, 0,114, 0, 5, 0, -110, 0,199, 2, 27, 0,168, 0, 0, 0, 19, 0, 2, 0,210, 2, 0, 0,211, 2,115, 0, 5, 0,110, 0,199, 2, 7, 0, 89, 0, - 7, 0,212, 2, 4, 0,213, 2, 4, 0,214, 2,116, 0, 5, 0,110, 0,199, 2, 27, 0,215, 2, 0, 0, 70, 0, 4, 0, 87, 1, - 4, 0, 18, 0,117, 0, 13, 0,110, 0,199, 2, 27, 0,216, 2, 27, 0,217, 2, 27, 0,218, 2, 27, 0,219, 2, 7, 0,220, 2, - 7, 0,221, 2, 7, 0,212, 2, 7, 0,222, 2, 4, 0,223, 2, 4, 0,224, 2, 4, 0, 92, 0, 4, 0,225, 2,118, 0, 5, 0, -110, 0,199, 2, 2, 0,226, 2, 2, 0, 18, 0, 7, 0,227, 2, 27, 0,228, 2,119, 0, 3, 0,110, 0,199, 2, 7, 0,229, 2, - 4, 0, 92, 0,120, 0, 10, 0,110, 0,199, 2, 7, 0,230, 2, 4, 0,231, 2, 4, 0, 27, 0, 2, 0, 92, 0, 2, 0,232, 2, - 2, 0,233, 2, 2, 0,234, 2, 7, 0,235, 2, 0, 0,236, 2,121, 0, 3, 0,110, 0,199, 2, 7, 0, 27, 0, 4, 0, 16, 0, -122, 0, 6, 0,110, 0,199, 2,123, 0,237, 2,124, 0,238, 2,125, 0,239, 2, 7, 0,240, 2, 4, 0, 16, 0,126, 0, 11, 0, -110, 0,199, 2, 47, 0,200, 2, 27, 0,201, 2, 0, 0,202, 2, 4, 0,203, 2, 4, 0,204, 2, 7, 0,209, 2, 4, 0,241, 2, - 0, 0,236, 2, 7, 0,242, 2, 4, 0, 27, 0,127, 0, 12, 0,110, 0,199, 2, 27, 0,243, 2, 42, 0,244, 2, 4, 0, 92, 0, - 4, 0,245, 2, 7, 0,246, 2, 7, 0,247, 2, 7, 0,248, 2, 7, 0,249, 2, 0, 0,202, 2, 4, 0,203, 2, 4, 0, 27, 0, -128, 0, 3, 0,110, 0,199, 2, 7, 0,250, 2, 4, 0,251, 2,129, 0, 5, 0,110, 0,199, 2, 7, 0,252, 2, 0, 0,236, 2, - 2, 0, 18, 0, 2, 0,253, 2,130, 0, 8, 0,110, 0,199, 2, 27, 0,168, 0, 7, 0,252, 2, 7, 0,255, 0, 7, 0,108, 0, - 0, 0,236, 2, 2, 0, 18, 0, 2, 0, 16, 0,131, 0, 21, 0,110, 0,199, 2, 47, 0,200, 2, 27, 0,201, 2, 0, 0,202, 2, - 4, 0,203, 2, 4, 0,204, 2, 27, 0,254, 2, 0, 0,236, 2, 2, 0, 18, 0, 2, 0, 27, 0, 7, 0,255, 2, 7, 0, 0, 3, - 7, 0, 1, 3, 7, 0, 81, 2, 7, 0, 2, 3, 7, 0, 3, 3, 7, 0, 4, 3, 7, 0, 5, 3, 7, 0, 6, 3, 7, 0, 7, 3, - 7, 0, 91, 0,132, 0, 7, 0,110, 0,199, 2, 2, 0, 8, 3, 2, 0, 9, 3, 4, 0, 30, 0, 27, 0,168, 0, 7, 0, 10, 3, - 0, 0,236, 2,133, 0, 10, 0,110, 0,199, 2, 27, 0,168, 0, 0, 0, 11, 3, 7, 0, 12, 3, 7, 0, 13, 3, 7, 0, 5, 3, - 4, 0, 14, 3, 4, 0, 15, 3, 7, 0, 16, 3, 0, 0, 19, 0,134, 0, 1, 0,110, 0,199, 2,135, 0, 7, 0,110, 0,199, 2, - 41, 0,125, 0,136, 0, 17, 3,137, 0, 18, 3,138, 0, 19, 3,139, 0, 20, 3, 14, 0, 21, 3,140, 0, 13, 0,110, 0,199, 2, - 88, 0, 22, 3, 88, 0, 23, 3, 88, 0, 24, 3, 88, 0, 25, 3, 88, 0, 26, 3, 88, 0, 27, 3, 85, 0, 28, 3, 4, 0, 29, 3, - 4, 0, 30, 3, 7, 0, 31, 3, 7, 0, 32, 3,141, 0, 33, 3,142, 0, 7, 0,110, 0,199, 2, 88, 0, 22, 3, 88, 0, 34, 3, -143, 0, 35, 3,144, 0, 33, 3, 4, 0, 36, 3, 4, 0, 29, 3,145, 0, 4, 0,110, 0,199, 2, 27, 0,168, 0, 4, 0, 37, 3, - 4, 0, 27, 0,146, 0, 2, 0, 4, 0, 38, 3, 7, 0, 39, 2,147, 0, 2, 0, 4, 0,128, 0, 4, 0, 39, 3,148, 0, 24, 0, -110, 0,199, 2, 27, 0,168, 0, 0, 0,236, 2, 2, 0, 40, 3, 2, 0, 18, 0, 2, 0, 87, 1, 2, 0, 27, 0,146, 0, 41, 3, - 4, 0, 42, 3, 7, 0, 43, 3, 4, 0, 53, 0, 4, 0, 44, 3,147, 0, 45, 3,146, 0, 46, 3, 4, 0, 47, 3, 4, 0, 48, 3, - 4, 0, 49, 3, 4, 0, 39, 3, 7, 0, 50, 3, 7, 0, 51, 3, 7, 0, 52, 3, 7, 0, 53, 3, 7, 0, 54, 3, 11, 0, 55, 3, -149, 0, 8, 0,110, 0,199, 2,150, 0, 56, 3,143, 0, 35, 3, 4, 0, 57, 3, 4, 0, 58, 3, 4, 0, 59, 3, 2, 0, 18, 0, - 2, 0, 56, 0,151, 0, 8, 0,110, 0,199, 2, 27, 0, 44, 0, 2, 0, 3, 1, 2, 0, 18, 0, 2, 0,226, 2, 2, 0, 56, 0, - 7, 0, 60, 3, 7, 0, 61, 3,152, 0, 6, 0,110, 0,199, 2, 4, 0, 62, 3, 2, 0, 18, 0, 2, 0, 63, 3, 7, 0, 64, 3, - 0, 0,170, 0,153, 0, 8, 0,110, 0,199, 2, 0, 0, 65, 3, 0, 0, 66, 3, 0, 0,193, 2, 0, 0, 67, 3, 0, 0, 68, 3, - 0, 0, 92, 0, 0, 0,181, 2,154, 0, 3, 0,110, 0,199, 2,155, 0, 69, 3,139, 0, 20, 3,156, 0, 10, 0,110, 0,199, 2, - 27, 0, 70, 3, 27, 0, 71, 3, 0, 0, 72, 3, 7, 0, 73, 3, 2, 0, 74, 3, 2, 0, 75, 3, 0, 0, 76, 3, 0, 0, 77, 3, - 0, 0,211, 2,157, 0, 9, 0,110, 0,199, 2, 27, 0, 78, 3, 0, 0, 72, 3, 7, 0, 79, 3, 7, 0, 80, 3, 0, 0, 87, 1, - 0, 0,226, 2, 0, 0, 81, 3, 0, 0, 27, 0,158, 0, 1, 0,110, 0,199, 2,159, 0, 11, 0,110, 0,199, 2, 0, 0,236, 2, - 7, 0,128, 0, 7, 0, 82, 3, 7, 0, 83, 3, 7, 0, 84, 3, 7, 0, 85, 3, 7, 0, 86, 3, 4, 0, 18, 0, 2, 0, 87, 3, - 2, 0, 88, 3,160, 0, 9, 0,110, 0,199, 2, 27, 0, 89, 3, 4, 0, 90, 3, 4, 0, 91, 3, 4, 0, 92, 3, 7, 0, 93, 3, - 7, 0, 94, 3, 2, 0,226, 2, 2, 0, 18, 0,161, 0, 29, 0,110, 0,199, 2,162, 0, 95, 3,163, 0, 96, 3, 4, 0, 97, 3, - 4, 0, 98, 3, 7, 0, 99, 3, 7, 0, 4, 3, 7, 0,100, 3, 7, 0,250, 0, 7, 0,101, 3, 7, 0,102, 3, 7, 0,103, 3, - 7, 0,104, 3, 7, 0,105, 3, 7, 0,240, 2, 4, 0,106, 3, 4, 0,107, 3, 0, 0,108, 3, 0, 0,109, 3, 0, 0,110, 3, - 0, 0,111, 3, 0, 0, 18, 0, 0, 0,112, 3, 2, 0,113, 3, 2, 0,114, 3, 4, 0,214, 2, 7, 0,108, 0, 7, 0,115, 3, - 4, 0, 27, 0,164, 0, 15, 0,110, 0,199, 2, 47, 0,200, 2, 27, 0,201, 2, 0, 0,202, 2, 4, 0,203, 2, 4, 0,204, 2, - 27, 0,116, 3, 27, 0,117, 3, 54, 0,100, 1, 0, 0,236, 2, 7, 0,209, 2, 7, 0,118, 3, 0, 0, 18, 0, 0, 0,253, 0, - 0, 0,211, 2,165, 0, 16, 0,110, 0,199, 2, 0, 0,236, 2, 2, 0,119, 3, 2, 0,253, 0, 7, 0,120, 3, 54, 0,121, 3, - 7, 0,122, 3, 7, 0,123, 3, 7, 0,124, 3, 0, 0,125, 3, 4, 0,126, 3, 47, 0,127, 3, 27, 0,128, 3, 4, 0,129, 3, - 0, 0,130, 3, 4, 0,131, 3,166, 0, 16, 0,110, 0,199, 2, 0, 0,132, 3, 0, 0,133, 3, 7, 0,134, 3, 7, 0,135, 3, - 0, 0,136, 3, 0, 0,137, 3, 0, 0,138, 3, 7, 0,124, 3, 0, 0,125, 3, 4, 0,126, 3, 47, 0,127, 3, 27, 0,128, 3, - 4, 0,129, 3, 0, 0,130, 3, 4, 0,131, 3,167, 0, 16, 0,110, 0,199, 2, 0, 0,236, 2, 4, 0,139, 3, 4, 0,140, 3, - 27, 0,141, 3, 7, 0,124, 3, 0, 0,125, 3, 4, 0,126, 3, 47, 0,127, 3, 27, 0,128, 3, 4, 0,129, 3, 0, 0,130, 3, - 7, 0,142, 3, 7, 0,143, 3, 2, 0,253, 0, 2, 0,144, 3,168, 0, 5, 0,110, 0,199, 2,169, 0,145, 3,170, 0,146, 3, - 4, 0, 16, 0, 4, 0, 27, 0,171, 0, 8, 0,110, 0,199, 2, 7, 0,147, 3, 7, 0,148, 3, 7, 0,149, 3, 0, 0,250, 0, - 0, 0, 18, 0, 0, 0, 87, 1, 0, 0, 27, 0,172, 0, 3, 0,173, 0,150, 3, 4, 0, 66, 2, 0, 0, 94, 0,173, 0, 29, 0, - 22, 0, 32, 0, 34, 0, 75, 0, 2, 0, 48, 2, 2, 0, 49, 2, 2, 0,151, 3, 2, 0, 18, 0, 2, 0,152, 3, 2, 0,153, 3, - 2, 0,154, 3, 2, 0, 30, 0, 0, 0,155, 3, 0, 0,156, 3, 0, 0,157, 3, 0, 0, 74, 0, 4, 0, 27, 0, 7, 0,158, 3, - 7, 0,159, 3, 7, 0,160, 3, 7, 0,161, 3, 7, 0,162, 3, 7, 0,163, 3, 29, 0,164, 3, 31, 0, 80, 0, 33, 0, 73, 2, - 90, 0,126, 2, 0, 0, 70, 0, 7, 0,165, 3, 7, 0,166, 3,172, 0,167, 3,174, 0, 5, 0,174, 0, 0, 0,174, 0, 1, 0, - 0, 0, 19, 0, 0, 0, 18, 0, 0, 0,124, 0, 68, 0, 3, 0, 7, 0,168, 3, 4, 0, 18, 0, 4, 0, 27, 0, 27, 0,128, 0, - 22, 0, 32, 0, 34, 0, 75, 0,175, 0,169, 3, 2, 0, 16, 0, 2, 0,170, 3, 4, 0,171, 3, 4, 0,172, 3, 4, 0,173, 3, - 0, 0,174, 3, 27, 0, 38, 0, 27, 0,175, 3, 27, 0,176, 3, 27, 0,177, 3, 27, 0,178, 3, 31, 0, 80, 0, 68, 0, 15, 2, -176, 0,179, 3,176, 0,180, 3,177, 0,181, 3, 11, 0, 2, 0,178, 0,182, 3,179, 0,183, 3,180, 0,184, 3, 14, 0,185, 3, - 14, 0,186, 3, 14, 0, 28, 2, 14, 0,187, 3, 14, 0,188, 3, 4, 0, 87, 1, 4, 0,189, 3, 63, 0, 30, 2, 0, 0,190, 3, - 4, 0, 32, 2, 4, 0,191, 3, 7, 0, 77, 1, 7, 0,192, 3, 7, 0,193, 3, 7, 0,176, 0, 7, 0,194, 3, 7, 0,195, 3, - 7, 0, 78, 1, 7, 0,196, 3, 7, 0, 18, 2, 7, 0,197, 3, 7, 0,198, 3, 7, 0,199, 3, 7, 0,200, 3, 7, 0,201, 3, - 7, 0,202, 3, 7, 0, 12, 3, 7, 0,203, 3, 7, 0,244, 0, 7, 0,204, 3, 4, 0,205, 3, 4, 0,206, 3, 2, 0, 18, 0, - 2, 0,207, 3, 2, 0,208, 3, 2, 0,209, 3, 2, 0,210, 3, 2, 0,211, 3, 2, 0,212, 3, 2, 0,213, 3, 2, 0,214, 3, - 0, 0,215, 3, 0, 0,216, 3, 4, 0,217, 3, 4, 0,218, 3, 4, 0,219, 3, 4, 0,220, 3, 7, 0,221, 3, 7, 0,108, 2, - 7, 0,222, 3, 7, 0,223, 3, 7, 0,224, 3, 7, 0,225, 3, 7, 0,226, 3, 7, 0,220, 0, 7, 0,227, 3, 7, 0,228, 3, - 7, 0,229, 3, 7, 0,230, 3, 7, 0,231, 3, 2, 0,232, 3, 0, 0,233, 3, 0, 0,234, 3, 0, 0,235, 3, 0, 0,236, 3, - 0, 0,110, 0, 0, 0,237, 3, 7, 0,238, 3, 7, 0,239, 3, 14, 0,240, 3, 14, 0,241, 3, 14, 0,242, 3, 14, 0,243, 3, - 7, 0,244, 3, 2, 0, 13, 2, 2, 0,245, 3, 7, 0,151, 2, 4, 0,246, 3, 4, 0,247, 3,181, 0,248, 3, 2, 0,249, 3, - 2, 0,251, 0, 7, 0,250, 3, 14, 0,251, 3, 14, 0,252, 3, 14, 0,253, 3, 14, 0,254, 3,182, 0, 73, 1,183, 0,255, 3, - 64, 0, 0, 4, 0, 0, 1, 4, 0, 0, 2, 4, 2, 0, 66, 2, 7, 0,143, 2,155, 0, 3, 4,143, 0, 4, 4,143, 0, 5, 4, - 10, 0, 6, 4, 10, 0, 7, 4, 4, 0, 8, 4, 4, 0, 9, 4, 14, 0, 10, 4, 14, 0, 11, 4, 14, 0, 12, 4, 7, 0, 13, 4, -184, 0, 14, 0,184, 0, 0, 0,184, 0, 1, 0, 27, 0, 38, 0, 7, 0, 12, 3, 7, 0, 79, 1, 7, 0, 13, 3, 7, 0, 5, 3, - 0, 0, 19, 0, 4, 0, 14, 3, 4, 0, 15, 3, 4, 0, 14, 4, 2, 0, 16, 0, 2, 0, 15, 4, 7, 0, 16, 3,185, 0, 12, 0, -185, 0, 0, 0,185, 0, 1, 0, 27, 0, 44, 0, 4, 0, 16, 4, 4, 0, 13, 2, 7, 0, 79, 1, 7, 0, 17, 4, 7, 0, 18, 4, - 7, 0,170, 2, 2, 0, 16, 0, 0, 0, 19, 4, 0, 0, 20, 4,182, 0, 40, 0, 4, 0, 18, 0, 2, 0, 21, 4, 2, 0, 22, 4, - 2, 0, 5, 3, 2, 0, 23, 4, 2, 0, 24, 4, 2, 0, 25, 4, 2, 0, 26, 4, 2, 0, 27, 4, 7, 0, 28, 4, 7, 0, 29, 4, - 7, 0, 30, 4, 7, 0, 31, 4, 7, 0, 32, 4, 7, 0, 33, 4, 7, 0, 34, 4, 7, 0, 35, 4, 7, 0, 36, 4, 7, 0, 37, 4, - 7, 0, 38, 4, 7, 0, 39, 4, 7, 0, 40, 4, 7, 0, 41, 4, 7, 0, 42, 4, 7, 0, 43, 4, 7, 0, 44, 4, 7, 0, 45, 4, - 7, 0, 46, 4, 7, 0, 47, 4, 7, 0, 48, 4, 7, 0, 49, 4, 7, 0, 50, 4, 7, 0, 51, 4, 7, 0, 52, 4, 7, 0, 53, 4, - 7, 0, 54, 4, 47, 0,169, 0,186, 0, 55, 4, 7, 0, 56, 4, 4, 0,214, 2,187, 0, 5, 0, 64, 0,249, 1, 7, 0, 57, 4, - 7, 0, 58, 4, 2, 0, 18, 0, 2, 0, 59, 4,188, 0, 5, 0,188, 0, 0, 0,188, 0, 1, 0, 4, 0, 16, 0, 4, 0, 60, 4, - 11, 0, 2, 0,189, 0, 9, 0,189, 0, 0, 0,189, 0, 1, 0, 4, 0, 61, 4, 4, 0, 62, 4, 4, 0, 63, 4, 4, 0, 18, 0, - 11, 0, 64, 4, 11, 0, 65, 4, 14, 0, 66, 4,139, 0, 23, 0,139, 0, 0, 0,139, 0, 1, 0, 4, 0, 18, 0, 4, 0, 67, 4, - 4, 0, 68, 4, 4, 0, 69, 4, 4, 0, 70, 4, 4, 0, 71, 4, 4, 0, 72, 4, 4, 0, 73, 4, 4, 0, 27, 0, 4, 0, 62, 4, - 4, 0, 13, 2, 2, 0, 74, 4, 2, 0, 56, 0, 0, 0, 19, 0, 0, 0, 75, 4, 0, 0, 76, 4, 0, 0, 77, 4, 0, 0, 78, 4, - 14, 0, 79, 4,190, 0, 80, 4, 11, 0, 81, 4,191, 0, 1, 0, 7, 0, 46, 2,181, 0, 30, 0, 4, 0, 18, 0, 7, 0, 82, 4, - 7, 0, 83, 4, 7, 0, 84, 4, 4, 0, 85, 4, 4, 0, 86, 4, 4, 0, 87, 4, 4, 0, 88, 4, 7, 0, 89, 4, 7, 0, 90, 4, - 7, 0, 91, 4, 7, 0, 92, 4, 7, 0, 93, 4, 7, 0, 94, 4, 7, 0, 95, 4, 7, 0, 96, 4, 7, 0, 97, 4, 7, 0, 98, 4, - 7, 0, 99, 4, 7, 0,100, 4, 7, 0,101, 4, 7, 0,102, 4, 7, 0,103, 4, 7, 0,104, 4, 7, 0,105, 4, 7, 0,106, 4, - 4, 0,107, 4, 4, 0,108, 4, 7, 0,109, 4, 7, 0,227, 3,183, 0, 54, 0, 4, 0, 62, 4, 4, 0,110, 4,192, 0,111, 4, -193, 0,112, 4, 0, 0, 27, 0, 0, 0,113, 4, 2, 0,114, 4, 7, 0,115, 4, 0, 0,116, 4, 7, 0,117, 4, 7, 0,118, 4, - 7, 0,119, 4, 7, 0,120, 4, 7, 0,121, 4, 7, 0,122, 4, 7, 0,123, 4, 7, 0,124, 4, 7, 0,125, 4, 2, 0,126, 4, - 0, 0,127, 4, 2, 0,128, 4, 7, 0,129, 4, 7, 0,130, 4, 0, 0,131, 4, 4, 0,129, 0, 4, 0,132, 4, 4, 0,133, 4, - 2, 0,134, 4, 2, 0,135, 4,191, 0,136, 4, 4, 0,137, 4, 4, 0, 82, 0, 7, 0,138, 4, 7, 0,139, 4, 7, 0,140, 4, - 7, 0,141, 4, 2, 0,142, 4, 2, 0,143, 4, 2, 0,144, 4, 2, 0,145, 4, 2, 0,146, 4, 2, 0,147, 4, 2, 0,148, 4, - 2, 0,149, 4,194, 0,150, 4, 7, 0,151, 4, 7, 0,152, 4,139, 0,153, 4, 14, 0, 21, 3,187, 0,154, 4, 7, 0,155, 4, - 7, 0,156, 4, 7, 0,157, 4, 4, 0,158, 4,195, 0, 1, 0, 7, 0,159, 4,155, 0, 52, 0,154, 0,160, 4, 2, 0, 16, 0, - 2, 0,161, 4, 2, 0,162, 4, 2, 0,163, 4, 7, 0,164, 4, 2, 0,165, 4, 2, 0,166, 4, 7, 0,167, 4, 2, 0,168, 4, - 2, 0,169, 4, 7, 0,170, 4, 7, 0,171, 4, 7, 0,172, 4, 4, 0,173, 4, 4, 0,174, 4, 4, 0,175, 4, 4, 0, 27, 0, - 7, 0,176, 4, 4, 0,177, 4, 7, 0,178, 4, 7, 0,179, 4, 7, 0,180, 4, 79, 0,181, 4, 79, 0,182, 4, 0, 0,183, 4, - 7, 0,184, 4, 7, 0,185, 4, 31, 0, 80, 0, 2, 0,186, 4, 0, 0,187, 4, 0, 0,188, 4, 7, 0,189, 4, 4, 0,190, 4, - 7, 0,191, 4, 7, 0,192, 4, 4, 0,193, 4, 4, 0, 18, 0, 7, 0,194, 4, 7, 0,195, 4, 7, 0,196, 4,195, 0,197, 4, - 4, 0, 53, 0, 7, 0,198, 4, 7, 0,199, 4, 7, 0,200, 4, 7, 0,201, 4, 7, 0,202, 4, 7, 0,203, 4, 7, 0,204, 4, - 4, 0,205, 4, 7, 0,206, 4,196, 0, 78, 0, 22, 0, 32, 0, 34, 0, 75, 0, 2, 0,179, 0, 2, 0, 88, 1, 2, 0,122, 1, - 2, 0,207, 4, 7, 0,208, 4, 7, 0,209, 4, 7, 0,210, 4, 7, 0,211, 4, 7, 0,212, 4, 7, 0,213, 4, 7, 0,170, 1, - 7, 0,172, 1, 7, 0,171, 1, 7, 0, 30, 0, 4, 0,214, 4, 7, 0,215, 4, 7, 0,216, 4, 7, 0,217, 4, 7, 0,218, 4, - 7, 0,219, 4, 7, 0,220, 4, 7, 0,221, 4, 2, 0,222, 4, 2, 0, 87, 1, 2, 0,223, 4, 2, 0,224, 4, 2, 0,225, 4, - 2, 0,226, 4, 2, 0,227, 4, 2, 0,228, 4, 7, 0,229, 4, 7, 0,230, 4, 7, 0,231, 4, 7, 0,232, 4, 7, 0,233, 4, - 7, 0,234, 4, 7, 0,235, 4, 7, 0,236, 4, 7, 0,237, 4, 7, 0,238, 4, 7, 0,239, 4, 7, 0,240, 4, 2, 0,241, 4, - 2, 0,242, 4, 2, 0,243, 4, 2, 0,244, 4, 7, 0,245, 4, 7, 0,246, 4, 7, 0,247, 4, 7, 0,248, 4, 2, 0,249, 4, - 2, 0,250, 4, 2, 0,251, 4, 2, 0,252, 4, 7, 0,253, 4, 7, 0,254, 4, 7, 0,255, 4, 7, 0, 0, 5, 7, 0, 1, 5, - 7, 0, 2, 5, 7, 0, 3, 5, 2, 0, 4, 5, 2, 0, 5, 5, 2, 0, 6, 5, 2, 0, 7, 5, 2, 0, 8, 5, 2, 0, 18, 0, - 7, 0, 9, 5, 7, 0, 10, 5, 31, 0, 80, 0, 46, 0,140, 1, 2, 0,141, 1, 2, 0, 76, 1, 2, 0,181, 2, 25, 0,154, 0, - 57, 0, 70, 1,197, 0, 8, 0,197, 0, 0, 0,197, 0, 1, 0, 4, 0,205, 3, 4, 0, 11, 5, 4, 0, 18, 0, 2, 0, 12, 5, - 2, 0, 13, 5, 27, 0,168, 0,198, 0, 13, 0, 11, 0, 14, 5, 11, 0, 15, 5, 4, 0, 16, 5, 4, 0, 17, 5, 4, 0, 18, 5, - 4, 0, 19, 5, 4, 0, 20, 5, 4, 0, 21, 5, 4, 0, 22, 5, 4, 0, 23, 5, 4, 0, 24, 5, 4, 0, 27, 0, 0, 0, 25, 5, -199, 0, 5, 0, 11, 0, 26, 5, 11, 0, 27, 5, 4, 0, 28, 5, 4, 0, 30, 0, 0, 0, 29, 5,200, 0, 17, 0, 4, 0, 30, 5, - 4, 0, 31, 5, 4, 0, 32, 5, 4, 0, 33, 5, 4, 0, 34, 5, 4, 0, 35, 5, 4, 0, 36, 5, 4, 0, 37, 5, 4, 0, 38, 5, - 4, 0, 39, 5, 4, 0, 40, 5, 4, 0, 41, 5, 2, 0, 42, 5, 2, 0, 43, 5, 4, 0, 44, 5, 4, 0, 45, 5, 4, 0, 91, 0, -201, 0, 17, 0, 4, 0, 16, 0, 4, 0, 32, 5, 4, 0, 46, 5, 4, 0, 47, 5, 4, 0, 48, 5, 4, 0, 49, 5, 4, 0, 50, 5, - 4, 0, 51, 5, 7, 0, 52, 5, 4, 0, 53, 5, 4, 0, 92, 0, 4, 0, 54, 5, 4, 0, 55, 5, 4, 0, 56, 5, 4, 0, 57, 5, - 4, 0, 58, 5, 21, 0, 31, 0,202, 0, 9, 0, 4, 0, 59, 5, 7, 0, 60, 5, 7, 0, 61, 5, 7, 0, 62, 5, 4, 0, 63, 5, - 2, 0, 18, 0, 2, 0, 27, 0, 7, 0, 84, 4, 7, 0, 30, 0,203, 0, 11, 0,203, 0, 0, 0,203, 0, 1, 0, 0, 0, 19, 0, - 63, 0, 64, 5, 64, 0, 65, 5, 4, 0,205, 3, 4, 0, 66, 5, 4, 0, 67, 5, 4, 0, 27, 0, 4, 0, 68, 5, 4, 0, 69, 5, -204, 0, 13, 0, 0, 0, 70, 5, 0, 0,250, 0, 0, 0, 71, 5, 0, 0, 18, 0, 0, 0, 72, 5, 0, 0, 73, 5, 0, 0, 74, 5, - 0, 0, 75, 5, 2, 0, 76, 5, 2, 0, 77, 5, 7, 0, 78, 5, 0, 0, 79, 5, 0, 0,124, 0,205, 0,106, 0,204, 0, 80, 5, -198, 0, 81, 5,199, 0, 82, 5,200, 0, 83, 5,201, 0, 84, 5, 4, 0, 36, 3, 4, 0,129, 0, 4, 0,132, 4, 7, 0, 85, 5, - 4, 0, 86, 5, 4, 0, 87, 5, 4, 0, 88, 5, 4, 0, 89, 5, 2, 0, 18, 0, 2, 0, 90, 5, 7, 0, 91, 5, 7, 0, 92, 5, - 7, 0, 93, 5, 7, 0, 94, 5, 7, 0, 95, 5, 2, 0, 96, 5, 2, 0, 97, 5, 2, 0, 98, 5, 2, 0, 99, 5, 2, 0,250, 0, - 2, 0,100, 5, 4, 0,101, 5, 2, 0,102, 5, 2, 0,103, 5, 2, 0,109, 1, 2, 0,108, 0, 2, 0,104, 5, 2, 0,105, 5, - 2, 0,106, 5, 2, 0,107, 5, 2, 0,108, 5, 2, 0, 71, 5, 2, 0, 70, 5, 2, 0,109, 5, 2, 0, 72, 5, 2, 0,110, 5, - 4, 0,111, 5, 4, 0, 87, 1, 4, 0,112, 5, 2, 0,113, 5, 2, 0, 91, 0, 2, 0,114, 5, 2, 0,115, 5, 2, 0,116, 5, - 2, 0,117, 5, 2, 0,118, 5, 2, 0,119, 5, 19, 0,120, 5, 19, 0,121, 5, 18, 0,122, 5, 14, 0,123, 5, 2, 0,124, 5, - 2, 0,125, 5, 7, 0,126, 5, 7, 0,127, 5, 7, 0,128, 5, 7, 0,129, 5, 4, 0,130, 5, 7, 0,131, 5, 7, 0,132, 5, - 7, 0,133, 5, 7, 0,134, 5, 2, 0,135, 5, 2, 0,136, 5, 2, 0,137, 5, 2, 0,138, 5, 2, 0,139, 5, 2, 0,140, 5, - 7, 0,141, 5, 7, 0,142, 5, 7, 0,143, 5, 0, 0,144, 5, 4, 0,145, 5, 2, 0,146, 5, 2, 0, 74, 0, 0, 0,147, 5, - 7, 0,148, 5, 7, 0,149, 5, 0, 0,150, 5, 0, 0,151, 5, 0, 0,152, 5, 0, 0,153, 5, 4, 0,154, 5, 2, 0,155, 5, - 2, 0,156, 5, 7, 0,157, 5, 7, 0,158, 5, 2, 0,159, 5, 2, 0,160, 5, 7, 0,161, 5, 2, 0,162, 5, 2, 0,163, 5, - 4, 0,164, 5, 2, 0,165, 5, 2, 0,166, 5, 2, 0,167, 5, 2, 0,168, 5, 7, 0,169, 5, 7, 0, 30, 0, 37, 0,170, 5, - 0, 0,171, 5,206, 0, 9, 0,206, 0, 0, 0,206, 0, 1, 0, 0, 0,172, 5, 2, 0,173, 5, 2, 0,174, 5, 2, 0,175, 5, - 2, 0, 91, 0, 7, 0,176, 5, 7, 0, 30, 0,207, 0, 7, 0, 2, 0,231, 2, 2, 0, 87, 1, 2, 0, 94, 3, 2, 0,177, 5, - 7, 0,178, 5, 7, 0, 30, 0, 37, 0,179, 5,208, 0, 5, 0, 7, 0,180, 5, 0, 0, 16, 0, 0, 0, 91, 0, 0, 0, 30, 0, - 0, 0, 74, 0,209, 0, 15, 0, 7, 0,181, 5, 7, 0,182, 5, 7, 0,183, 5, 7, 0,184, 5, 7, 0,185, 5, 7, 0,186, 5, - 7, 0,187, 5, 7, 0,188, 5, 7, 0,189, 5, 7, 0,190, 5, 4, 0,191, 5, 7, 0,192, 5, 7, 0,193, 5, 2, 0, 91, 0, - 2, 0, 30, 0,210, 0, 32, 0,208, 0,194, 5, 2, 0,195, 5, 2, 0, 97, 5, 2, 0, 98, 5, 2, 0, 99, 5, 2, 0,250, 0, - 2, 0,100, 5, 2, 0,196, 5, 2, 0,197, 5, 2, 0,198, 5, 2, 0,199, 5,207, 0,200, 5, 2, 0,201, 5, 2, 0,102, 5, - 7, 0,202, 5,209, 0,203, 5, 7, 0,220, 4, 7, 0,221, 4, 4, 0, 18, 0, 2, 0, 87, 1, 2, 0,204, 5, 2, 0,223, 4, - 2, 0,224, 4, 2, 0,205, 5, 2, 0, 27, 0, 2, 0,225, 4, 2, 0,226, 4, 2, 0,227, 4, 2, 0,228, 4, 2, 0,206, 5, - 2, 0, 91, 0, 7, 0,207, 5,211, 0, 6, 0,211, 0, 0, 0,211, 0, 1, 0, 4, 0, 61, 4, 0, 0, 19, 0, 4, 0, 18, 0, - 27, 0,208, 5,212, 0, 4, 0,213, 0,146, 3, 11, 0,209, 5, 0, 0,210, 5, 4, 0, 92, 0,214, 0, 8, 0,212, 0,211, 5, - 2, 0, 18, 0, 2, 0, 27, 0, 2, 0,212, 5, 2, 0,213, 5, 2, 0,214, 5, 4, 0, 91, 0, 11, 0,215, 5,215, 0, 6, 0, - 2, 0,108, 0, 2, 0, 67, 4, 2, 0,216, 5, 2, 0,225, 2, 4, 0, 18, 0, 7, 0,209, 2,216, 0, 14, 0, 2, 0, 18, 0, - 2, 0,217, 5, 2, 0,218, 5, 2, 0,219, 5,215, 0,220, 5, 11, 0,215, 5, 7, 0,221, 5, 7, 0, 56, 0, 4, 0,222, 5, - 4, 0,223, 5, 4, 0,224, 5, 4, 0,225, 5, 41, 0,125, 0, 27, 0,168, 0,217, 0, 14, 0,212, 0,211, 5, 4, 0, 92, 0, - 4, 0,226, 5, 7, 0,227, 5, 7, 0,228, 5, 7, 0,229, 5, 4, 0,230, 5, 4, 0,231, 5, 7, 0,232, 5, 7, 0,233, 5, - 4, 0,234, 5, 7, 0,235, 5, 7, 0,236, 5, 4, 0, 27, 0,218, 0, 1, 0,212, 0,211, 5,219, 0, 7, 0,212, 0,211, 5, - 2, 0, 18, 0, 2, 0, 27, 0, 4, 0, 37, 0, 4, 0,237, 5, 90, 0,238, 5, 11, 0,215, 5,220, 0, 5, 0,220, 0, 0, 0, -220, 0, 1, 0, 0, 0, 19, 0, 7, 0,239, 5, 4, 0, 27, 0,221, 0, 4, 0, 4, 0,108, 0, 7, 0,240, 5, 7, 0,178, 1, - 4, 0, 18, 0,222, 0, 85, 0,219, 0,241, 5,219, 0,242, 5,217, 0,169, 3,218, 0,243, 5, 7, 0,244, 5, 2, 0,245, 5, - 2, 0,246, 5, 7, 0,247, 5, 7, 0,248, 5, 2, 0, 67, 4, 2, 0,249, 5, 7, 0,250, 5, 7, 0,251, 5, 7, 0,252, 5, - 2, 0,253, 5, 2, 0,222, 5, 2, 0,254, 5, 2, 0,255, 5, 2, 0, 0, 6, 2, 0, 1, 6, 7, 0, 2, 6, 7, 0, 3, 6, - 7, 0, 4, 6, 2, 0, 5, 6, 2, 0, 6, 6, 2, 0, 7, 6, 2, 0, 8, 6, 2, 0, 9, 6, 2, 0, 10, 6, 2, 0, 11, 6, - 2, 0, 12, 6,214, 0, 13, 6,216, 0, 14, 6, 7, 0, 15, 6, 7, 0, 16, 6, 7, 0, 17, 6, 2, 0, 18, 6, 2, 0, 19, 6, - 0, 0, 20, 6, 0, 0, 21, 6, 2, 0, 22, 6, 7, 0, 23, 6, 7, 0, 24, 6, 7, 0, 25, 6, 7, 0, 26, 6, 7, 0, 27, 6, - 7, 0, 28, 6, 7, 0, 29, 6, 7, 0, 30, 6, 7, 0, 31, 6, 7, 0, 32, 6, 2, 0, 33, 6, 0, 0, 34, 6, 0, 0, 35, 6, - 0, 0, 36, 6, 0, 0, 37, 6, 27, 0, 38, 6, 0, 0, 39, 6, 0, 0, 40, 6, 0, 0, 41, 6, 0, 0, 42, 6, 0, 0, 43, 6, - 0, 0, 44, 6, 0, 0, 45, 6, 0, 0, 46, 6, 0, 0, 47, 6, 0, 0, 48, 6, 2, 0, 49, 6, 2, 0, 50, 6, 2, 0, 51, 6, - 2, 0, 52, 6, 0, 0, 53, 6, 0, 0, 54, 6, 0, 0, 55, 6, 0, 0, 56, 6, 4, 0, 57, 6, 4, 0, 58, 6, 4, 0, 59, 6, - 4, 0, 60, 6, 2, 0, 61, 6, 2, 0, 91, 0, 4, 0, 62, 6, 7, 0, 63, 6, 7, 0, 64, 6,221, 0, 65, 6,223, 0, 8, 0, - 4, 0, 66, 6, 4, 0, 67, 6, 4, 0, 68, 6, 4, 0, 69, 6, 4, 0, 70, 6, 4, 0, 71, 6, 4, 0, 53, 0, 4, 0,138, 2, -224, 0, 4, 0, 7, 0, 72, 6, 0, 0, 73, 6, 0, 0, 74, 6, 2, 0, 18, 0,225, 0, 4, 0, 7, 0, 75, 6, 4, 0, 18, 0, - 4, 0, 76, 6, 4, 0, 56, 0, 41, 0, 46, 0, 22, 0, 32, 0, 34, 0, 75, 0, 27, 0,208, 5,196, 0, 77, 6, 41, 0, 78, 6, - 14, 0, 79, 6,197, 0, 80, 6, 27, 0, 81, 6, 7, 0, 82, 6, 7, 0, 83, 6, 7, 0, 84, 6, 7, 0, 85, 6, 4, 0,205, 3, - 4, 0, 86, 6, 4, 0, 87, 6, 2, 0, 18, 0, 2, 0, 76, 1, 57, 0, 70, 1,226, 0, 88, 6,222, 0, 89, 6,227, 0, 90, 6, -205, 0,185, 0,202, 0, 91, 6, 14, 0,102, 0, 14, 0, 92, 6, 11, 0, 93, 6, 11, 0, 94, 6, 11, 0, 95, 6, 11, 0, 96, 6, - 11, 0, 97, 6,228, 0, 98, 6, 2, 0, 99, 6, 2, 0,100, 6, 2, 0,251, 0, 2, 0,206, 3, 4, 0,216, 3, 4, 0,101, 6, - 14, 0,102, 6,208, 0,194, 5,210, 0,103, 6,224, 0,104, 6,178, 0,182, 3,225, 0,105, 6,229, 0,106, 6, 10, 0, 7, 4, - 10, 0,107, 6,230, 0, 14, 0,230, 0, 0, 0,230, 0, 1, 0, 42, 0,242, 0, 40, 0, 69, 1,229, 0,106, 6,231, 0,108, 6, - 7, 0, 96, 2, 7, 0, 97, 2, 7, 0,108, 0, 7, 0,109, 6, 2, 0,110, 6, 2, 0, 18, 0, 2, 0,143, 0, 2, 0, 27, 0, -232, 0, 39, 0, 7, 0,111, 6, 7, 0,112, 6, 7, 0,113, 6, 7, 0,114, 6, 7, 0,115, 6, 7, 0,116, 6, 7, 0,117, 6, - 7, 0,118, 6, 7, 0,119, 6, 68, 0,120, 6,178, 0,182, 3,232, 0,121, 6,233, 0,122, 6,234, 0,123, 6,235, 0,124, 6, -236, 0,125, 6,237, 0,126, 6, 7, 0,127, 6, 7, 0,128, 6, 7, 0, 94, 1, 7, 0,129, 6, 7, 0,130, 6, 7, 0,131, 6, - 7, 0,132, 6, 7, 0,175, 0, 7, 0,133, 6, 0, 0,134, 6, 0, 0,135, 6, 0, 0,110, 6, 0, 0,136, 6, 2, 0,137, 6, - 2, 0,138, 6, 7, 0,139, 6, 2, 0,140, 6, 2, 0,141, 6, 7, 0,142, 6, 7, 0,143, 6, 7, 0,144, 6, 7, 0,145, 6, -238, 0, 51, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, 7, 0,128, 6, - 7, 0, 94, 1, 7, 0,150, 6, 2, 0,151, 6, 0, 0,211, 2, 4, 0,152, 6, 2, 0,135, 6, 2, 0,110, 6, 27, 0,208, 5, - 27, 0,153, 6, 14, 0,154, 6,230, 0,155, 6,238, 0,121, 6, 0, 0,156, 6, 4, 0,205, 3, 4, 0, 86, 6, 2, 0,157, 6, - 2, 0,158, 6, 2, 0,159, 6, 2, 0,160, 6, 2, 0, 18, 0, 2, 0, 31, 2, 7, 0,114, 0, 7, 0,161, 6, 7, 0,162, 6, - 7, 0,163, 6, 7, 0,175, 0, 7, 0, 82, 6, 2, 0,164, 6, 2, 0,165, 6, 2, 0,166, 6, 0, 0,167, 6, 0, 0,168, 6, - 0, 0,169, 6, 0, 0,170, 6, 0, 0,171, 6, 14, 0,172, 6, 14, 0,173, 6, 14, 0,174, 6, 2, 0,175, 6, 2, 0,152, 2, - 2, 0,176, 6, 0, 0,177, 6, 11, 0,178, 6,178, 0,182, 3,240, 0, 24, 0, 19, 0, 37, 0, 19, 0, 63, 0, 18, 0,179, 6, - 18, 0,180, 6, 18, 0,181, 6, 7, 0,182, 6, 7, 0,183, 6, 7, 0,184, 6, 7, 0,185, 6, 2, 0,186, 6, 2, 0,187, 6, - 2, 0,188, 6, 2, 0,189, 6, 2, 0,190, 6, 2, 0, 18, 0, 2, 0,191, 6, 2, 0,192, 6, 2, 0,193, 6, 2, 0,194, 6, - 2, 0,195, 6, 2, 0,160, 6, 7, 0,196, 6, 4, 0,197, 6, 4, 0,198, 6,239, 0, 6, 0,239, 0, 0, 0,239, 0, 1, 0, - 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6,241, 0, 8, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, - 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, 0, 0,199, 6, 0, 0,124, 0,242, 0, 14, 0,239, 0, 0, 0,239, 0, 1, 0, - 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6,240, 0,200, 6,243, 0,201, 6, 14, 0,202, 6, 2, 0, 87, 1, - 2, 0,203, 6, 4, 0, 18, 0, 7, 0,204, 6, 4, 0,160, 6,244, 0, 21, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, - 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6,240, 0,200, 6, 2, 0,205, 6, 2, 0,206, 6, 2, 0,207, 6, 2, 0,208, 6, - 2, 0,191, 6, 2, 0,209, 6, 2, 0,210, 6, 0, 0, 18, 0, 0, 0, 27, 0, 11, 0, 72, 2, 4, 0,211, 6, 4, 0,212, 6, - 22, 0,213, 6, 11, 0,214, 6,245, 0, 18, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, - 2, 0,149, 6,240, 0,200, 6, 7, 0, 96, 2, 7, 0, 97, 2, 2, 0,205, 6, 2, 0,215, 6, 2, 0,216, 6, 2, 0,217, 6, - 4, 0, 18, 0, 7, 0,218, 6, 4, 0,110, 6, 4, 0, 27, 0,178, 0,182, 3,246, 0, 16, 0, 0, 0,219, 6, 0, 0,220, 6, - 0, 0,221, 6, 0, 0,222, 6, 0, 0,223, 6, 0, 0,224, 6, 4, 0,225, 6, 4, 0,226, 6, 4, 0,227, 6, 2, 0, 16, 0, - 2, 0, 18, 0, 2, 0,228, 6, 2, 0,229, 6, 2, 0,190, 1, 2, 0,230, 6, 0, 0,231, 6,247, 0, 16, 0,239, 0, 0, 0, -239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 4, 0,232, 6,246, 0,233, 6,248, 0,234, 6, 14, 0,235, 6, 14, 0,236, 6, -249, 0,237, 6,237, 0,238, 6,250, 0,239, 6, 2, 0,240, 6, 2, 0,241, 6, 2, 0,242, 6, 2, 0, 30, 0,251, 0, 15, 0, -239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6,240, 0,200, 6, 14, 0,243, 6, -252, 0,244, 6, 0, 0,245, 6,253, 0,246, 6, 2, 0, 18, 0, 2, 0,247, 6, 2, 0,248, 6, 2, 0,249, 6,254, 0, 25, 0, -239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 4, 0, 18, 0, 42, 0,244, 2, 40, 0, 69, 1, 54, 0,250, 6, -255, 0,251, 6, 0, 1,252, 6,178, 0,182, 3, 7, 0,253, 6, 7, 0, 96, 2, 7, 0, 97, 2, 7, 0,218, 6, 7, 0,254, 6, - 7, 0,255, 6, 2, 0, 0, 7, 2, 0, 27, 0, 2, 0, 1, 7, 2, 0, 2, 7, 0, 0, 3, 7, 0, 0, 4, 7, 0, 0, 5, 7, - 0, 0,160, 6, 1, 1, 11, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, - 2, 0,203, 6, 2, 0, 18, 0, 4, 0, 27, 0,243, 0,201, 6,240, 0,200, 6, 2, 1, 31, 0,239, 0, 0, 0,239, 0, 1, 0, - 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, 37, 0, 6, 7, 4, 0, 7, 7, 4, 0, 8, 7, 2, 0, 92, 0, - 2, 0, 9, 7, 2, 0, 10, 7, 0, 0, 11, 7, 0, 0, 12, 7, 4, 0, 13, 7, 4, 0, 14, 7, 4, 0, 15, 7, 2, 0, 16, 7, - 2, 0, 17, 7, 2, 0, 18, 7, 2, 0, 19, 7, 7, 0, 20, 7, 18, 0, 21, 7, 18, 0, 22, 7, 4, 0, 23, 7, 4, 0, 24, 7, - 0, 0, 25, 7, 0, 0, 26, 7, 2, 0, 27, 7, 0, 0,211, 2, 11, 0, 28, 7, 3, 1, 10, 0, 22, 0, 32, 0, 11, 0, 29, 7, - 11, 0, 30, 7, 11, 0, 31, 7, 11, 0, 32, 7, 11, 0, 33, 7, 4, 0, 92, 0, 4, 0, 34, 7, 0, 0, 35, 7, 0, 0, 36, 7, - 4, 1, 10, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 3, 1, 37, 7, 2, 0, 92, 0, - 2, 0, 9, 7, 4, 0, 91, 0, 11, 0, 38, 7, 5, 1, 3, 0, 5, 1, 0, 0, 5, 1, 1, 0, 7, 0, 39, 7, 6, 1, 9, 0, -239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6,240, 0,200, 6, 14, 0, 40, 7, 4, 0, 41, 7, - 4, 0, 18, 0, 7, 1, 27, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, -240, 0,200, 6, 22, 0, 42, 7, 22, 0, 81, 0, 2, 0, 18, 0, 2, 0, 91, 0, 7, 0, 43, 7, 7, 0, 96, 2, 7, 0, 97, 2, - 7, 0,218, 6, 7, 0, 44, 7, 7, 0, 45, 7, 7, 0, 46, 7, 57, 0, 70, 1, 57, 0, 47, 7, 4, 0, 48, 7, 2, 0, 49, 7, - 2, 0, 50, 7, 2, 0,251, 0, 2, 0, 86, 1, 14, 0, 51, 7,178, 0,182, 3, 8, 1, 10, 0,239, 0, 0, 0,239, 0, 1, 0, - 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, 2, 0, 18, 0, 2, 0,214, 3, 4, 0, 27, 0,178, 0,182, 3, - 9, 1, 7, 0, 9, 1, 0, 0, 9, 1, 1, 0, 4, 0, 52, 7, 4, 0, 22, 0, 0, 0, 85, 0, 4, 0, 53, 7, 4, 0, 16, 0, - 10, 1, 14, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, 4, 0, 10, 7, - 4, 0, 27, 0, 14, 0, 54, 7, 14, 0, 55, 7, 0, 0, 56, 7, 0, 0, 57, 7, 4, 0, 58, 7, 4, 0, 59, 7, 11, 1, 6, 0, -239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 4, 0, 27, 0, 0, 0, 60, 7, 12, 1, 24, 0,239, 0, 0, 0, -239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0, 96, 2, 7, 0, 97, 2, 7, 0, 61, 7, 7, 0, 62, 7, 7, 0,218, 6, -231, 0, 63, 7,229, 0,106, 6, 13, 1,251, 6, 4, 0, 18, 0, 2, 0, 87, 1, 2, 0,110, 6, 4, 0, 64, 7, 7, 0, 65, 7, - 7, 0,148, 3, 7, 0, 94, 3, 4, 0, 27, 0, 7, 0, 66, 7, 7, 0, 67, 7, 4, 0, 68, 7, 4, 0, 69, 7, 14, 1, 7, 0, - 14, 1, 0, 0, 14, 1, 1, 0, 0, 0, 70, 7, 2, 0, 71, 7, 2, 0, 72, 7, 2, 0, 73, 7, 2, 0, 27, 0, 15, 1, 12, 0, - 2, 0, 72, 7, 2, 0, 74, 7, 2, 0, 75, 7, 0, 0,211, 2, 2, 0, 76, 7, 2, 0, 77, 7, 2, 0, 78, 7, 2, 0, 79, 7, - 2, 0, 80, 7, 2, 0,191, 6, 7, 0, 81, 7, 7, 0, 82, 7, 16, 1, 18, 0, 16, 1, 0, 0, 16, 1, 1, 0, 0, 0, 19, 0, - 15, 1, 83, 7, 15, 1, 84, 7, 15, 1, 85, 7, 15, 1, 86, 7, 7, 0, 87, 7, 2, 0, 88, 7, 2, 0, 89, 7, 2, 0, 90, 7, - 2, 0, 91, 7, 2, 0, 92, 7, 2, 0, 93, 7, 2, 0, 94, 7, 2, 0, 95, 7, 2, 0, 96, 7, 2, 0, 27, 0, 17, 1, 10, 0, - 0, 0, 97, 7, 0, 0, 98, 7, 0, 0, 99, 7, 0, 0,100, 7, 0, 0,101, 7, 0, 0,102, 7, 2, 0,103, 7, 2, 0,104, 7, - 2, 0,105, 7, 2, 0,106, 7, 18, 1, 8, 0, 0, 0,107, 7, 0, 0,108, 7, 0, 0,109, 7, 0, 0,110, 7, 0, 0,111, 7, - 0, 0,112, 7, 7, 0,109, 6, 7, 0, 27, 0, 19, 1, 3, 0, 0, 0,113, 7, 2, 0,114, 7, 2, 0, 27, 0, 20, 1, 22, 0, - 17, 1,115, 7, 17, 1,116, 7, 17, 1,117, 7, 17, 1,118, 7, 17, 1,119, 7, 17, 1,120, 7, 17, 1,121, 7, 17, 1,122, 7, - 17, 1,123, 7, 17, 1,124, 7, 17, 1,125, 7, 17, 1,126, 7, 17, 1,127, 7, 17, 1,128, 7, 17, 1,129, 7, 17, 1,130, 7, - 17, 1,131, 7, 18, 1,132, 7, 19, 1,133, 7, 0, 0,134, 7, 7, 0,135, 7, 7, 0, 27, 0, 21, 1,122, 0, 0, 0,136, 7, - 0, 0,137, 7, 0, 0,101, 7, 0, 0,138, 7, 0, 0,113, 7, 0, 0,139, 7, 0, 0,140, 7, 0, 0,141, 7, 0, 0,142, 7, - 0, 0,143, 7, 0, 0,144, 7, 0, 0,145, 7, 0, 0,146, 7, 0, 0,147, 7, 0, 0,148, 7, 0, 0,149, 7, 0, 0,150, 7, - 0, 0,151, 7, 0, 0,152, 7, 0, 0,153, 7, 0, 0,154, 7, 0, 0,155, 7, 0, 0,156, 7, 0, 0,157, 7, 0, 0,158, 7, - 0, 0,159, 7, 0, 0,160, 7, 0, 0,161, 7, 0, 0,162, 7, 0, 0,163, 7, 0, 0,164, 7, 0, 0,165, 7, 0, 0,166, 7, - 0, 0,167, 7, 0, 0,168, 7, 0, 0,169, 7, 0, 0,170, 7, 0, 0,171, 7, 0, 0,172, 7, 0, 0,173, 7, 0, 0,174, 7, - 0, 0,175, 7, 0, 0,176, 7, 0, 0,177, 7, 0, 0,178, 7, 0, 0,179, 7, 0, 0,180, 7, 0, 0,181, 7, 0, 0,182, 7, - 0, 0,183, 7, 0, 0,184, 7, 0, 0,185, 7, 0, 0,186, 7, 0, 0,187, 7, 0, 0,188, 7, 0, 0,189, 7, 0, 0,190, 7, - 0, 0,191, 7, 0, 0,192, 7, 0, 0,193, 7, 0, 0,194, 7, 0, 0,195, 7, 0, 0,196, 7, 0, 0,197, 7, 0, 0,198, 7, - 0, 0,199, 7, 0, 0,200, 7, 0, 0,201, 7, 0, 0,202, 7, 0, 0,203, 7, 0, 0,204, 7, 0, 0,205, 7, 0, 0,206, 7, - 0, 0,207, 7, 0, 0,208, 7, 0, 0,209, 7, 0, 0,210, 7, 0, 0,211, 7, 0, 0,212, 7, 0, 0,213, 7, 0, 0,214, 7, - 0, 0,215, 7, 0, 0,216, 7, 0, 0,217, 7, 0, 0,218, 7, 0, 0,219, 7, 0, 0,220, 7, 0, 0,221, 7, 0, 0,222, 7, - 0, 0,223, 7, 0, 0,224, 7, 0, 0,225, 7, 0, 0,226, 7, 0, 0,227, 7, 0, 0,228, 7, 0, 0,229, 7, 0, 0,230, 7, - 0, 0,231, 7, 0, 0,232, 7, 0, 0,233, 7, 0, 0,234, 7, 0, 0,235, 7, 0, 0,236, 7, 0, 0,237, 7, 0, 0,238, 7, - 0, 0,239, 7, 0, 0,240, 7, 0, 0,241, 7, 0, 0,242, 7, 0, 0,243, 7, 0, 0,244, 7, 0, 0,245, 7, 0, 0,246, 7, - 0, 0,247, 7, 0, 0,248, 7, 0, 0,249, 7, 0, 0,250, 7, 0, 0,251, 7, 0, 0,252, 7, 0, 0,253, 7, 0, 0,254, 7, - 0, 0,255, 7, 22, 1, 5, 0, 0, 0, 0, 8, 0, 0,159, 7, 0, 0,165, 7, 2, 0, 18, 0, 2, 0, 27, 0, 23, 1, 24, 0, - 23, 1, 0, 0, 23, 1, 1, 0, 0, 0,172, 5, 20, 1, 1, 8, 21, 1, 2, 8, 21, 1, 3, 8, 21, 1, 4, 8, 21, 1, 5, 8, - 21, 1, 6, 8, 21, 1, 7, 8, 21, 1, 8, 8, 21, 1, 9, 8, 21, 1, 10, 8, 21, 1, 11, 8, 21, 1, 12, 8, 21, 1, 13, 8, - 21, 1, 14, 8, 21, 1, 15, 8, 21, 1, 16, 8, 21, 1, 17, 8, 21, 1, 18, 8, 22, 1, 19, 8, 4, 0, 20, 8, 4, 0, 27, 0, - 24, 1, 3, 0, 24, 1, 0, 0, 24, 1, 1, 0, 0, 0, 21, 8, 25, 1, 5, 0, 4, 0, 18, 0, 4, 0, 27, 0, 7, 0,151, 2, - 7, 0, 22, 8, 7, 0, 46, 2, 26, 1, 95, 0, 4, 0, 18, 0, 4, 0, 23, 8, 4, 0, 24, 8, 0, 0, 25, 8, 0, 0, 26, 8, - 0, 0, 27, 8, 0, 0, 28, 8, 0, 0, 29, 8, 0, 0, 30, 8, 0, 0, 31, 8, 0, 0, 32, 8, 0, 0, 33, 8, 0, 0, 34, 8, - 4, 0, 35, 8, 2, 0, 36, 8, 2, 0, 37, 8, 2, 0, 38, 8, 2, 0, 39, 8, 4, 0, 40, 8, 4, 0, 41, 8, 4, 0, 42, 8, - 4, 0, 43, 8, 2, 0, 44, 8, 2, 0, 45, 8, 4, 0, 46, 8, 4, 0, 47, 8, 4, 0, 48, 8, 4, 0, 49, 8, 4, 0, 50, 8, - 4, 0, 54, 7, 4, 0, 51, 8, 2, 0, 52, 8, 2, 0, 53, 8, 2, 0, 54, 8, 2, 0, 55, 8, 14, 0, 56, 8, 14, 0, 57, 8, - 14, 0, 58, 8, 14, 0, 59, 8, 14, 0, 60, 8, 14, 0, 61, 8, 0, 0, 62, 8, 2, 0, 63, 8, 2, 0, 64, 8, 2, 0, 65, 8, - 2, 0, 66, 8, 2, 0, 67, 8, 2, 0, 68, 8, 2, 0, 69, 8, 2, 0, 70, 8, 25, 1, 71, 8, 2, 0, 72, 8, 2, 0, 73, 8, - 2, 0, 74, 8, 2, 0, 75, 8, 2, 0, 76, 8, 2, 0, 77, 8, 2, 0, 78, 8, 2, 0, 79, 8, 4, 0, 80, 8, 4, 0, 81, 8, - 2, 0, 82, 8, 2, 0, 83, 8, 2, 0, 84, 8, 2, 0, 85, 8, 2, 0, 86, 8, 2, 0, 87, 8, 2, 0, 88, 8, 2, 0, 89, 8, - 2, 0, 90, 8, 2, 0, 91, 8, 2, 0, 92, 8, 2, 0, 93, 8, 2, 0, 94, 8, 2, 0, 95, 8, 2, 0, 96, 8, 2, 0, 97, 8, - 2, 0, 98, 8, 2, 0, 99, 8, 7, 0,100, 8, 4, 0,101, 8, 7, 0,102, 8, 2, 0, 18, 6, 2, 0, 19, 6, 2, 0,103, 8, - 2, 0,104, 8, 50, 0,105, 8, 7, 0,106, 8, 2, 0,107, 8, 2, 0, 74, 0, 0, 0,108, 8, 4, 0,109, 8, 4, 0,110, 8, - 7, 0,111, 8, 7, 0, 27, 0, 27, 1, 24, 0, 22, 0, 32, 0, 14, 0,112, 8, 14, 0,113, 8, 14, 0,114, 8, 14, 0,146, 6, - 41, 0,125, 0, 41, 0,115, 8, 4, 0,116, 8, 4, 0, 91, 0, 2, 0,117, 8, 2, 0,118, 8, 2, 0,119, 8, 2, 0,120, 8, - 2, 0,121, 8, 2, 0,122, 8, 2, 0,123, 8, 2, 0,124, 8, 2, 0,125, 8, 2, 0,126, 8, 2, 0,127, 8, 2, 0, 27, 0, -237, 0,128, 8, 11, 0,129, 8, 2, 0,130, 8, 28, 1, 5, 0, 28, 1, 0, 0, 28, 1, 1, 0, 28, 1,131, 8, 15, 0,132, 8, - 4, 0, 18, 0, 29, 1, 7, 0, 29, 1, 0, 0, 29, 1, 1, 0, 28, 1,133, 8, 28, 1,134, 8, 2, 0,121, 5, 2, 0, 18, 0, - 4, 0, 27, 0, 30, 1, 25, 0, 30, 1, 0, 0, 30, 1, 1, 0, 31, 1,135, 8, 32, 1,239, 6, 0, 0,136, 8, 0, 0,137, 8, - 0, 0,138, 8, 2, 0,139, 8, 2, 0,140, 8, 2, 0,141, 8, 2, 0,142, 8, 2, 0,143, 8, 2, 0, 27, 0, 2, 0, 18, 0, - 2, 0, 69, 7, 2, 0,144, 8, 2, 0,145, 8, 4, 0,146, 8, 30, 1,147, 8, 11, 0,148, 8, 4, 0,149, 8, 4, 0,150, 8, - 4, 0,151, 8, 4, 0,152, 8, 0, 0,153, 8, 33, 1, 22, 0, 33, 1, 0, 0, 33, 1, 1, 0, 28, 1,133, 8, 28, 1,134, 8, - 28, 1,154, 8, 28, 1,155, 8, 27, 1,156, 8, 18, 0, 51, 0, 0, 0,147, 6, 0, 0,157, 8, 2, 0,192, 6, 2, 0,193, 6, - 2, 0,158, 8, 2, 0, 27, 0, 2, 0,121, 8, 2, 0, 53, 7, 2, 0, 18, 0, 34, 1,135, 8, 14, 0,159, 8, 14, 0,146, 6, - 14, 0,160, 8, 14, 0,161, 8, 35, 1, 24, 0, 35, 1, 0, 0, 35, 1, 1, 0,240, 0,200, 6, 18, 0,162, 8, 18, 0,163, 8, - 2, 0,192, 6, 2, 0,193, 6, 2, 0,164, 8, 2, 0,165, 8, 2, 0,166, 8, 2, 0, 18, 0, 7, 0, 92, 2, 2, 0,141, 8, - 2, 0,142, 8, 2, 0,120, 8, 2, 0,167, 8, 2, 0,125, 8, 2, 0, 86, 1, 36, 1,135, 8, 14, 0,168, 8, 14, 0,169, 8, - 14, 0,160, 8, 0, 0,170, 8, 11, 0,171, 8, 37, 1, 14, 0, 0, 0,172, 8, 2, 0,173, 8, 2, 0,174, 8, 2, 0,175, 8, - 2, 0,176, 8, 2, 0,110, 5, 2, 0,177, 8, 27, 1,178, 8, 41, 0,179, 8, 4, 0,180, 8, 4, 0,181, 8, 4, 0,182, 8, - 4, 0, 27, 0, 0, 0, 70, 7, 38, 1, 3, 0, 0, 0,183, 8, 4, 0,184, 8, 4, 0,185, 8, 39, 1, 4, 0, 4, 0, 7, 7, - 4, 0,186, 8, 4, 0, 13, 7, 4, 0,187, 8, 40, 1, 2, 0, 4, 0,188, 8, 4, 0,189, 8, 41, 1, 5, 0, 7, 0,190, 8, - 7, 0,191, 8, 7, 0,192, 8, 4, 0, 18, 0, 4, 0, 27, 0, 42, 1, 7, 0, 0, 0,193, 8, 0, 0,221, 6, 44, 0,138, 0, - 2, 0,194, 8, 2, 0, 72, 5, 2, 0,195, 8, 2, 0,196, 8, 43, 1, 12, 0, 43, 1, 0, 0, 43, 1, 1, 0, 4, 0, 28, 0, - 4, 0,197, 8, 4, 0,198, 8, 4, 0,199, 8, 38, 1,200, 8, 0, 0,193, 8, 42, 1,176, 3, 39, 1,201, 8, 40, 1,202, 8, - 41, 1,203, 8, 44, 1, 12, 0, 0, 0, 35, 0, 11, 0,227, 0, 0, 0,228, 0, 4, 0,231, 0, 4, 0,239, 0, 11, 0,232, 0, - 7, 0,234, 0, 7, 0,235, 0, 11, 0,204, 8, 11, 0,205, 8, 11, 0,236, 0, 11, 0,238, 0, 45, 1, 48, 0, 45, 1, 0, 0, - 45, 1, 1, 0, 11, 0,206, 8, 11, 0, 25, 0, 0, 0, 19, 0, 4, 0, 18, 0, 4, 0, 16, 0, 4, 0, 22, 0, 4, 0, 89, 0, - 4, 0,207, 8, 4, 0,208, 8, 4, 0,198, 8, 4, 0,199, 8, 4, 0,209, 8, 4, 0,250, 0, 4, 0,210, 8, 4, 0,211, 8, - 7, 0,212, 8, 7, 0,213, 8, 7, 0,214, 8, 2, 0,215, 8, 2, 0,216, 8, 4, 0,217, 8, 4, 0,218, 8, 43, 1,219, 8, - 31, 0, 80, 0, 41, 0,125, 0, 27, 0,220, 8, 44, 0,138, 0,229, 0,106, 6, 7, 0,221, 8, 7, 0,222, 8, 44, 1, 71, 1, - 45, 1,223, 8, 45, 1,224, 8, 45, 1,225, 8, 14, 0,226, 8, 46, 1,227, 8, 11, 0,228, 8, 7, 0, 84, 4, 7, 0,229, 8, - 7, 0,230, 8, 7, 0,231, 8, 11, 0,232, 8, 4, 0,233, 8, 4, 0,234, 8, 4, 0,235, 8, 7, 0,236, 8, 47, 1, 4, 0, - 47, 1, 0, 0, 47, 1, 1, 0, 14, 0,237, 8, 45, 1,238, 8,226, 0, 11, 0, 14, 0,239, 8, 14, 0,226, 8, 14, 0,240, 8, - 45, 1,241, 8, 0, 0,242, 8, 0, 0,243, 8, 4, 0,244, 8, 4, 0,245, 8, 4, 0,246, 8, 4, 0, 27, 0, 19, 0,247, 8, - 48, 1, 4, 0, 7, 0,248, 8, 7, 0, 94, 3, 2, 0,249, 8, 2, 0,250, 8, 49, 1, 6, 0, 7, 0,251, 8, 7, 0,252, 8, - 7, 0,253, 8, 7, 0,254, 8, 4, 0,255, 8, 4, 0, 0, 9, 50, 1, 8, 0, 7, 0, 1, 9, 7, 0, 2, 9, 7, 0, 3, 9, - 7, 0, 4, 9, 7, 0, 5, 9, 4, 0,250, 2, 4, 0, 6, 9, 4, 0, 7, 9, 51, 1, 2, 0, 7, 0,180, 5, 7, 0, 27, 0, - 52, 1, 5, 0, 7, 0, 8, 9, 7, 0, 9, 9, 4, 0, 92, 0, 4, 0,212, 2, 4, 0, 10, 9, 53, 1, 6, 0, 53, 1, 0, 0, - 53, 1, 1, 0, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 11, 9, 2, 0, 56, 0, 54, 1, 8, 0, 54, 1, 0, 0, 54, 1, 1, 0, - 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 11, 9, 2, 0, 56, 0, 7, 0, 22, 0, 7, 0,129, 0, 55, 1, 45, 0, 55, 1, 0, 0, - 55, 1, 1, 0, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 11, 9, 2, 0,246, 0, 2, 0,126, 4, 2, 0, 12, 9, 7, 0, 13, 9, - 7, 0, 90, 0, 7, 0, 7, 3, 4, 0, 14, 9, 4, 0, 82, 0, 4, 0,214, 2, 7, 0, 15, 9, 7, 0, 16, 9, 7, 0, 17, 9, - 7, 0, 18, 9, 7, 0, 19, 9, 7, 0, 20, 9, 7, 0, 4, 3, 7, 0, 68, 1, 7, 0, 21, 9, 7, 0, 22, 9, 7, 0, 27, 0, - 7, 0, 23, 9, 7, 0, 24, 9, 7, 0, 25, 9, 2, 0, 26, 9, 2, 0, 27, 9, 2, 0, 28, 9, 2, 0, 29, 9, 2, 0, 30, 9, - 2, 0, 31, 9, 2, 0, 32, 9, 2, 0, 33, 9, 2, 0, 31, 2, 2, 0, 34, 9, 2, 0, 28, 2, 2, 0, 35, 9, 0, 0, 36, 9, - 0, 0, 37, 9, 7, 0,244, 0, 56, 1, 38, 9, 64, 0,249, 1, 57, 1, 16, 0, 57, 1, 0, 0, 57, 1, 1, 0, 2, 0, 16, 0, - 2, 0, 18, 0, 2, 0, 11, 9, 2, 0,246, 0, 7, 0,255, 2, 7, 0, 0, 3, 7, 0, 1, 3, 7, 0, 81, 2, 7, 0, 2, 3, - 7, 0, 3, 3, 7, 0, 39, 9, 7, 0, 4, 3, 7, 0, 6, 3, 7, 0, 7, 3,253, 0, 5, 0, 2, 0, 16, 0, 2, 0, 40, 9, - 2, 0, 18, 0, 2, 0, 41, 9, 22, 0, 42, 7,252, 0, 3, 0, 4, 0, 68, 0, 4, 0, 42, 9,253, 0, 2, 0, 58, 1, 7, 0, - 58, 1, 0, 0, 58, 1, 1, 0, 0, 0, 19, 0, 2, 0, 16, 0, 2, 0, 18, 0, 4, 0, 21, 0, 11, 0, 43, 9, 59, 1, 5, 0, - 0, 0, 19, 0, 7, 0, 94, 1, 7, 0, 44, 9, 4, 0, 45, 9, 4, 0, 27, 0, 60, 1, 4, 0, 2, 0, 16, 0, 2, 0, 18, 0, - 2, 0, 91, 0, 2, 0, 30, 0, 61, 1, 4, 0, 0, 0, 19, 0, 63, 0, 46, 9, 7, 0, 94, 1, 7, 0, 27, 0, 62, 1, 6, 0, - 2, 0, 47, 9, 2, 0, 48, 9, 2, 0, 16, 0, 2, 0, 49, 9, 0, 0, 50, 9, 0, 0, 51, 9, 63, 1, 5, 0, 4, 0, 16, 0, - 4, 0, 27, 0, 0, 0, 19, 0, 0, 0, 52, 9, 0, 0, 53, 9, 64, 1, 3, 0, 4, 0, 16, 0, 4, 0, 27, 0, 0, 0, 19, 0, - 65, 1, 4, 0, 2, 0, 54, 9, 2, 0, 55, 9, 2, 0, 18, 0, 2, 0, 27, 0, 66, 1, 6, 0, 0, 0, 19, 0, 0, 0, 56, 9, - 2, 0, 57, 9, 2, 0, 4, 3, 2, 0, 87, 1, 2, 0, 30, 0, 67, 1, 5, 0, 0, 0, 19, 0, 7, 0, 94, 3, 7, 0,217, 4, - 2, 0, 18, 0, 2, 0,226, 2, 68, 1, 3, 0, 0, 0, 19, 0, 4, 0,214, 2, 4, 0, 54, 9, 69, 1, 7, 0, 0, 0, 19, 0, - 7, 0,217, 4, 0, 0, 58, 9, 0, 0, 59, 9, 2, 0, 87, 1, 2, 0, 91, 0, 4, 0, 60, 9, 70, 1, 4, 0, 0, 0, 61, 9, - 0, 0, 62, 9, 4, 0, 16, 0, 7, 0,230, 2, 71, 1, 3, 0, 27, 0, 63, 9, 0, 0, 64, 9, 0, 0, 65, 9, 72, 1, 18, 0, - 72, 1, 0, 0, 72, 1, 1, 0, 2, 0, 16, 0, 2, 0, 66, 9, 2, 0, 18, 0, 2, 0, 67, 9, 2, 0, 68, 9, 2, 0, 69, 9, - 2, 0, 91, 0, 2, 0, 30, 0, 0, 0, 19, 0, 11, 0, 2, 0, 73, 1, 70, 9, 27, 0, 44, 0, 2, 0,216, 5, 2, 0,176, 2, - 2, 0, 71, 9, 2, 0, 27, 0, 74, 1, 11, 0, 0, 0, 19, 0, 0, 0, 16, 0, 0, 0, 72, 9, 2, 0, 18, 0, 2, 0,226, 2, - 2, 0, 73, 9, 4, 0, 74, 9, 4, 0, 75, 9, 4, 0, 76, 9, 4, 0, 77, 9, 4, 0, 78, 9, 75, 1, 1, 0, 0, 0, 79, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0,114,114,114,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,130,130,130,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 57,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,170, 64,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, + 32,255,255,255, 75, 75, 75,255,204, 0,153,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 32, 0, 0,255, 0, 32, 0,255, + 0, 0,128,255, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255,255,255,255,255, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 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,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,200,200,200,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76,255, + 0, 0, 0, 0,250,250,250,255, 15, 15, 15,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100,255,140, 25,255,250,250,250,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,130,130,130,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,250,250,250,255, 0, 0, 0, 0, +250,250,250,255,250,250,250,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 79,101, 73,255,135,177,125,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255,153, 64, 48,255, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, +240,175,144,255, 82, 96,110,255,124,137,150,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 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,255,255,255,128, + 0, 0, 0,255,255,133, 0,255, 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,114,114,114,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 79,101, 73,255,135,177,125,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 12, 10, 10,128,255,140, 0,255, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 82, 96,110,255,124,137,150,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 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,255,255,255,128, + 0, 0, 0,255,255,133, 0,255, 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,107,107,107,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 79,101, 73,255,135,177,125,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 12, 10, 10,128,255,140, 0,255, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 82, 96,110,255,124,137,150,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 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,255,255,255,128, + 0, 0, 0,255,255,133, 0,255, 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,116,116,116,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81,105,135,255, 32, 32,143,255, +109, 88,129,255, 78,152, 62,255, 46,143,143,255,169, 84,124,255,126,126, 80,255,162, 95,111,255,109,145,131,255,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 53, 53,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0,255,255,255, 10,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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,114,114,255, 18, 66,176, 38, +255,133, 0,178,255,133, 0,127, 0,255, 0,255,255, 0, 0,255,225,210,195, 35, 0, 0, 0, 0, 0, 0, 0, 0,153,153,153,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,143,143,143,255,198,119,119,255,255, 0, 0,255, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 4, 0,100, 0, 0,255, 0, 0,200,255,128, 0, 80,255, 95, 95, 0,255, 0,100, 50,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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,114,114,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51,127, 51, 76,130,135,140, 76,114,114,114,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,173,173,173,255,127,112,112,100, 0, 0, 0, 0, 91, 91, 91,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 57,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,255,255,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 4, 5,155,155,155,160,100,104,111,255,111,106,100,255,104,106,117,255,105,117,110,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100,100,100,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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,114,114,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 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,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,140, 25,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, +255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 0, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255, 0, 0, 0, 0, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,128,255,255,255,255,255,255, 0,170, 0,255,220, 96, 96,255,220, 96, 96,255, + 3, 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,255,255,255,128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 57,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 94, 94, 94,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,170, 64,255, + 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, + 32,255,255,255, 75, 75, 75,255,204, 0,153,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 32, 0, 0,255, 0, 32, 0,255, + 0, 0,128,255, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 12, 10, 10,128,255,140, 0,255, + 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255,240,144,160,255,255,255,255,255, 0, 0, 0,255, +144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0, 0, 0, 0, 0,255,240,255, 64,255, 64,192, 48,255,240,144,160,255, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 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,255,255,255,128, + 0, 0, 0,255,255,255, 0,255, 4, 0, 0, 0,255,127,127, 0,255,255,255,255,255,255,255, 0,255,127, 0, 0,255,127,127,127, +255,200,200,200,255,255, 0, 0,255, 0, 0,255,255, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 0, 0,255, +189, 17, 17,255,247, 10, 10,255, 0, 0, 0, 0,247, 64, 24,255,246,105, 19,255,250,153, 0,255, 0, 0, 0, 0, 30,145, 9,255, + 89,183, 11,255,131,239, 29,255, 0, 0, 0, 0, 10, 54,148,255, 54,103,223,255, 94,193,239,255, 0, 0, 0, 0,169, 41, 78,255, +193, 65,106,255,240, 93,145,255, 0, 0, 0, 0, 67, 12,120,255, 84, 58,163,255,135,100,213,255, 0, 0, 0, 0, 36,120, 90,255, + 60,149,121,255,111,182,171,255, 0, 0, 0, 0, 75,112,124,255,106,134,145,255,155,194,205,255, 0, 0, 0, 0,244,201, 12,255, +238,194, 54,255,243,255, 0,255, 0, 0, 0, 0, 30, 32, 36,255, 72, 76, 86,255,255,255,255,255, 0, 0, 0, 0,111, 47,106,255, +152, 69,190,255,211, 48,214,255, 0, 0, 0, 0,108,142, 34,255,127,176, 34,255,187,239, 91,255, 0, 0, 0, 0,141,141,141,255, +176,176,176,255,222,222,222,255, 0, 0, 0, 0,131, 67, 38,255,139, 88, 17,255,189,106, 17,255, 0, 0, 0, 0, 8, 49, 14,255, + 28, 67, 11,255, 52, 98, 43,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0,136,154,198, 6, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0, 40,155,198, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,111, 95,115, 99,101,110,101, 95, 51,100,115, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0, 40,155,198, 6, 0, 0, 0, 0,207, 0, 0, 0, + 1, 0, 0, 0,104,238,199, 6, 0, 0, 0, 0,136,154,198, 6, 0, 0, 0, 0,105,111, 95,115, 99,101,110,101, 95,102, 98,120, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0,104,238,199, 6, + 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0, 8,239,199, 6, 0, 0, 0, 0, 40,155,198, 6, 0, 0, 0, 0,105,111, 95, 97, +110,105,109, 95, 98,118,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 80, 0, 0, 0, 8,239,199, 6, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0,168,239,199, 6, 0, 0, 0, 0,104,238,199, 6, + 0, 0, 0, 0,105,111, 95,109,101,115,104, 95,112,108,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0,168,239,199, 6, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0, 72,240,199, 6, + 0, 0, 0, 0, 8,239,199, 6, 0, 0, 0, 0,105,111, 95,115, 99,101,110,101, 95,111, 98,106, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0, 72,240,199, 6, 0, 0, 0, 0,207, 0, 0, 0, + 1, 0, 0, 0,232,240,199, 6, 0, 0, 0, 0,168,239,199, 6, 0, 0, 0, 0,105,111, 95,115, 99,101,110,101, 95,120, 51,100, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0,232,240,199, 6, + 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0,136,241,199, 6, 0, 0, 0, 0, 72,240,199, 6, 0, 0, 0, 0,105,111, 95,109, +101,115,104, 95,115,116,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 80, 0, 0, 0,136,241,199, 6, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0, 40,242,199, 6, 0, 0, 0, 0,232,240,199, 6, + 0, 0, 0, 0,105,111, 95,109,101,115,104, 95,117,118, 95,108, 97,121,111,117,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, 68, 65, 84, 65, 80, 0, 0, 0, 40,242,199, 6, 0, 0, 0, 0,207, 0, 0, 0, 1, 0, 0, 0,200,242,199, 6, + 0, 0, 0, 0,136,241,199, 6, 0, 0, 0, 0,105,111, 95, 99,117,114,118,101, 95,115,118,103, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0,200,242,199, 6, 0, 0, 0, 0,207, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,242,199, 6, 0, 0, 0, 0, 99,121, 99,108,101,115, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,232, 0, 0, 0,104,243,199, 6, + 0, 0, 0, 0,199, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,101,102, 97, +117,108,116, 32, 83,116,121,108,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,255,255, 0, 0,154,153, 25, 62, 0, 0,128, 63, 0, 0, 12, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,255,255, 0, 0, 0, 0,128, 62, 0, 0, 0, 0, 0, 0, 11, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,255,255, 0, 0,154,153, 25, 62, 0, 0,128, 63, 0, 0, 11, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 8, 0, 5, 0, 5, 0, 8, 0, 2, 0, 8, 0, 4, 0, 0, 0, 68, 78, 65, 49,156, 4, 1, 0, 24, 9,236, 0, + 73,127, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 83, 68, 78, 65, 78, 65, 77, 69, 58, 13, 0, 0, 42,110,101,120,116, 0, 42,112, +114,101,118, 0, 42,100, 97,116, 97, 0, 42,102,105,114,115,116, 0, 42,108, 97,115,116, 0,120, 0,121, 0,122, 0,120,109,105, +110, 0,120,109, 97,120, 0,121,109,105,110, 0,121,109, 97,120, 0, 42,112,111,105,110,116,101,114, 0,103,114,111,117,112, 0, +118, 97,108, 0,118, 97,108, 50, 0,116,121,112,101, 0,115,117, 98,116,121,112,101, 0,102,108, 97,103, 0,110, 97,109,101, 91, + 54, 52, 93, 0,115, 97,118,101,100, 0,100, 97,116, 97, 0,108,101,110, 0,116,111,116, 97,108,108,101,110, 0, 42,110,101,119, +105,100, 0, 42,108,105, 98, 0,110, 97,109,101, 91, 54, 54, 93, 0,112, 97,100, 0,117,115, 0,105, 99,111,110, 95,105,100, 0, +112, 97,100, 50, 0, 42,112,114,111,112,101,114,116,105,101,115, 0,105,100, 0, 42,105,100, 98,108,111, 99,107, 0, 42,102,105, +108,101,100, 97,116, 97, 0,110, 97,109,101, 91, 49, 48, 50, 52, 93, 0,102,105,108,101,112, 97,116,104, 91, 49, 48, 50, 52, 93, + 0,116,111,116, 0, 42,112, 97,114,101,110,116, 0,119, 91, 50, 93, 0,104, 91, 50, 93, 0, 99,104, 97,110,103,101,100, 91, 50, + 93, 0, 99,104, 97,110,103,101,100, 95,116,105,109,101,115,116, 97,109,112, 91, 50, 93, 0, 42,114,101, 99,116, 91, 50, 93, 0, + 42,111, 98, 0, 98,108,111, 99,107,116,121,112,101, 0, 97,100,114, 99,111,100,101, 0,110, 97,109,101, 91, 49, 50, 56, 93, 0, + 42, 98,112, 0, 42, 98,101,122,116, 0,109, 97,120,114, 99,116, 0,116,111,116,114, 99,116, 0,118, 97,114,116,121,112,101, 0, +116,111,116,118,101,114,116, 0,105,112,111, 0,101,120,116,114, 97,112, 0,114,116, 0, 98,105,116,109, 97,115,107, 0,115,108, +105,100,101, 95,109,105,110, 0,115,108,105,100,101, 95,109, 97,120, 0, 99,117,114,118, 97,108, 0, 42,100,114,105,118,101,114, + 0, 99,117,114,118,101, 0, 99,117,114, 0,115,104,111,119,107,101,121, 0,109,117,116,101,105,112,111, 0,112,111,115, 0,112, + 97,100, 49, 0,114,101,108, 97,116,105,118,101, 0,116,111,116,101,108,101,109, 0,117,105,100, 0, 42,119,101,105,103,104,116, +115, 0,118,103,114,111,117,112, 91, 54, 52, 93, 0,115,108,105,100,101,114,109,105,110, 0,115,108,105,100,101,114,109, 97,120, + 0, 42, 97,100,116, 0, 42,114,101,102,107,101,121, 0,101,108,101,109,115,116,114, 91, 51, 50, 93, 0,101,108,101,109,115,105, +122,101, 0, 98,108,111, 99,107, 0, 42,105,112,111, 0, 42,102,114,111,109, 0,116,111,116,107,101,121, 0,115,108,117,114,112, +104, 0, 99,116,105,109,101, 0,117,105,100,103,101,110, 0, 42,108,105,110,101, 0, 42,102,111,114,109, 97,116, 0, 98,108,101, +110, 0,108,105,110,101,110,111, 0,115,116, 97,114,116, 0,101,110,100, 0,102,108, 97,103,115, 0, 99,111,108,111,114, 91, 52, + 93, 0,112, 97,100, 91, 52, 93, 0, 42,110, 97,109,101, 0,110,108,105,110,101,115, 0,108,105,110,101,115, 0, 42, 99,117,114, +108, 0, 42,115,101,108,108, 0, 99,117,114, 99, 0,115,101,108, 99, 0,109, 97,114,107,101,114,115, 0, 42,117,110,100,111, 95, + 98,117,102, 0,117,110,100,111, 95,112,111,115, 0,117,110,100,111, 95,108,101,110, 0, 42, 99,111,109,112,105,108,101,100, 0, +109,116,105,109,101, 0,115,105,122,101, 0,115,101,101,107, 0,100,116,120, 0,112, 97,115,115,101,112, 97,114,116, 97,108,112, +104, 97, 0, 99,108,105,112,115,116, 97, 0, 99,108,105,112,101,110,100, 0,108,101,110,115, 0,111,114,116,104,111, 95,115, 99, + 97,108,101, 0,100,114, 97,119,115,105,122,101, 0,115,101,110,115,111,114, 95,120, 0,115,101,110,115,111,114, 95,121, 0,115, +104,105,102,116,120, 0,115,104,105,102,116,121, 0, 89, 70, 95,100,111,102,100,105,115,116, 0, 42,100,111,102, 95,111, 98, 0, +115,101,110,115,111,114, 95,102,105,116, 0,112, 97,100, 91, 55, 93, 0, 42,115, 99,101,110,101, 0,102,114, 97,109,101,110,114, + 0,102,114, 97,109,101,115, 0,111,102,102,115,101,116, 0,115,102,114, 97, 0,102,105,101, 95,105,109, 97, 0, 99,121, 99,108, + 0,111,107, 0,109,117,108,116,105, 95,105,110,100,101,120, 0,108, 97,121,101,114, 0,112, 97,115,115, 0,105, 98,117,102,115, + 0, 42,103,112,117,116,101,120,116,117,114,101, 0, 42, 97,110,105,109, 0, 42,114,114, 0, 42,114,101,110,100,101,114,115, 91, + 56, 93, 0,114,101,110,100,101,114, 95,115,108,111,116, 0,108, 97,115,116, 95,114,101,110,100,101,114, 95,115,108,111,116, 0, +115,111,117,114, 99,101, 0,108, 97,115,116,102,114, 97,109,101, 0,116,112, 97,103,101,102,108, 97,103, 0,116,111,116, 98,105, +110,100, 0,120,114,101,112, 0,121,114,101,112, 0,116,119,115,116, 97, 0,116,119,101,110,100, 0, 98,105,110,100, 99,111,100, +101, 0, 42,114,101,112, 98,105,110,100, 0, 42,112, 97, 99,107,101,100,102,105,108,101, 0, 42,112,114,101,118,105,101,119, 0, +108, 97,115,116,117,112,100, 97,116,101, 0,108, 97,115,116,117,115,101,100, 0, 97,110,105,109,115,112,101,101,100, 0,103,101, +110, 95,120, 0,103,101,110, 95,121, 0,103,101,110, 95,116,121,112,101, 0,103,101,110, 95,102,108, 97,103, 0, 97,115,112,120, + 0, 97,115,112,121, 0,116,101,120, 99,111, 0,109, 97,112,116,111, 0,109, 97,112,116,111,110,101,103, 0, 98,108,101,110,100, +116,121,112,101, 0, 42,111, 98,106,101, 99,116, 0, 42,116,101,120, 0,117,118,110, 97,109,101, 91, 54, 52, 93, 0,112,114,111, +106,120, 0,112,114,111,106,121, 0,112,114,111,106,122, 0,109, 97,112,112,105,110,103, 0,111,102,115, 91, 51, 93, 0,115,105, +122,101, 91, 51, 93, 0,114,111,116, 0,116,101,120,102,108, 97,103, 0, 99,111,108,111,114,109,111,100,101,108, 0,112,109, 97, +112,116,111, 0,112,109, 97,112,116,111,110,101,103, 0,110,111,114,109, 97,112,115,112, 97, 99,101, 0,119,104,105, 99,104, 95, +111,117,116,112,117,116, 0, 98,114,117,115,104, 95,109, 97,112, 95,109,111,100,101, 0,114, 0,103, 0, 98, 0,107, 0,100,101, +102, 95,118, 97,114, 0, 99,111,108,102, 97, 99, 0,118, 97,114,102, 97, 99, 0,110,111,114,102, 97, 99, 0,100,105,115,112,102, + 97, 99, 0,119, 97,114,112,102, 97, 99, 0, 99,111,108,115,112,101, 99,102, 97, 99, 0,109,105,114,114,102, 97, 99, 0, 97,108, +112,104, 97,102, 97, 99, 0,100,105,102,102,102, 97, 99, 0,115,112,101, 99,102, 97, 99, 0,101,109,105,116,102, 97, 99, 0,104, + 97,114,100,102, 97, 99, 0,114, 97,121,109,105,114,114,102, 97, 99, 0,116,114, 97,110,115,108,102, 97, 99, 0, 97,109, 98,102, + 97, 99, 0, 99,111,108,101,109,105,116,102, 97, 99, 0, 99,111,108,114,101,102,108,102, 97, 99, 0, 99,111,108,116,114, 97,110, +115,102, 97, 99, 0,100,101,110,115,102, 97, 99, 0,115, 99, 97,116,116,101,114,102, 97, 99, 0,114,101,102,108,102, 97, 99, 0, +116,105,109,101,102, 97, 99, 0,108,101,110,103,116,104,102, 97, 99, 0, 99,108,117,109,112,102, 97, 99, 0,100, 97,109,112,102, + 97, 99, 0,107,105,110,107,102, 97, 99, 0,114,111,117,103,104,102, 97, 99, 0,112, 97,100,101,110,115,102, 97, 99, 0,103,114, + 97,118,105,116,121,102, 97, 99, 0,108,105,102,101,102, 97, 99, 0,115,105,122,101,102, 97, 99, 0,105,118,101,108,102, 97, 99, + 0,102,105,101,108,100,102, 97, 99, 0,115,104, 97,100,111,119,102, 97, 99, 0,122,101,110,117,112,102, 97, 99, 0,122,101,110, +100,111,119,110,102, 97, 99, 0, 98,108,101,110,100,102, 97, 99, 0, 42,104, 97,110,100,108,101, 0, 42,112,110, 97,109,101, 0, + 42,115,116,110, 97,109,101,115, 0,115,116,121,112,101,115, 0,118, 97,114,115, 0, 42,118, 97,114,115,116,114, 0, 42,114,101, +115,117,108,116, 0, 42, 99,102,114, 97, 0,100, 97,116, 97, 91, 51, 50, 93, 0, 40, 42,100,111,105,116, 41, 40, 41, 0, 40, 42, +105,110,115,116, 97,110, 99,101, 95,105,110,105,116, 41, 40, 41, 0, 40, 42, 99, 97,108,108, 98, 97, 99,107, 41, 40, 41, 0,118, +101,114,115,105,111,110, 0, 97, 0,105,112,111,116,121,112,101, 0, 42,105,109, 97, 0, 42, 99,117, 98,101, 91, 54, 93, 0,105, +109, 97,116, 91, 52, 93, 91, 52, 93, 0,111, 98,105,109, 97,116, 91, 51, 93, 91, 51, 93, 0,115,116,121,112,101, 0,118,105,101, +119,115, 99, 97,108,101, 0,110,111,116,108, 97,121, 0, 99,117, 98,101,114,101,115, 0,100,101,112,116,104, 0,114,101, 99, 97, +108, 99, 0,108, 97,115,116,115,105,122,101, 0,102, 97,108,108,111,102,102, 95,116,121,112,101, 0,102, 97,108,108,111,102,102, + 95,115,111,102,116,110,101,115,115, 0,114, 97,100,105,117,115, 0, 99,111,108,111,114, 95,115,111,117,114, 99,101, 0,116,111, +116,112,111,105,110,116,115, 0,112,100,112, 97,100, 0,112,115,121,115, 0,112,115,121,115, 95, 99, 97, 99,104,101, 95,115,112, + 97, 99,101, 0,111, 98, 95, 99, 97, 99,104,101, 95,115,112, 97, 99,101, 0, 42,112,111,105,110,116, 95,116,114,101,101, 0, 42, +112,111,105,110,116, 95,100, 97,116, 97, 0,110,111,105,115,101, 95,115,105,122,101, 0,110,111,105,115,101, 95,100,101,112,116, +104, 0,110,111,105,115,101, 95,105,110,102,108,117,101,110, 99,101, 0,110,111,105,115,101, 95, 98, 97,115,105,115, 0,112,100, +112, 97,100, 51, 91, 51, 93, 0,110,111,105,115,101, 95,102, 97, 99, 0,115,112,101,101,100, 95,115, 99, 97,108,101, 0,102, 97, +108,108,111,102,102, 95,115,112,101,101,100, 95,115, 99, 97,108,101, 0,112,100,112, 97,100, 50, 0, 42, 99,111, 98, 97, 0, 42, +102, 97,108,108,111,102,102, 95, 99,117,114,118,101, 0,114,101,115,111,108, 91, 51, 93, 0,105,110,116,101,114,112, 95,116,121, +112,101, 0,102,105,108,101, 95,102,111,114,109, 97,116, 0,101,120,116,101,110,100, 0,115,109,111,107,101,100, 95,116,121,112, +101, 0,105,110,116, 95,109,117,108,116,105,112,108,105,101,114, 0,115,116,105,108,108, 95,102,114, 97,109,101, 0,115,111,117, +114, 99,101, 95,112, 97,116,104, 91, 49, 48, 50, 52, 93, 0, 42,100, 97,116, 97,115,101,116, 0, 99, 97, 99,104,101,100,102,114, + 97,109,101, 0,111, 99,101, 97,110,109,111,100, 91, 54, 52, 93, 0,111,117,116,112,117,116, 0,110,111,105,115,101,115,105,122, +101, 0,116,117,114, 98,117,108, 0, 98,114,105,103,104,116, 0, 99,111,110,116,114, 97,115,116, 0,115, 97,116,117,114, 97,116, +105,111,110, 0,114,102, 97, 99, 0,103,102, 97, 99, 0, 98,102, 97, 99, 0,102,105,108,116,101,114,115,105,122,101, 0,109,103, + 95, 72, 0,109,103, 95,108, 97, 99,117,110, 97,114,105,116,121, 0,109,103, 95,111, 99,116, 97,118,101,115, 0,109,103, 95,111, +102,102,115,101,116, 0,109,103, 95,103, 97,105,110, 0,100,105,115,116, 95, 97,109,111,117,110,116, 0,110,115, 95,111,117,116, +115, 99, 97,108,101, 0,118,110, 95,119, 49, 0,118,110, 95,119, 50, 0,118,110, 95,119, 51, 0,118,110, 95,119, 52, 0,118,110, + 95,109,101,120,112, 0,118,110, 95,100,105,115,116,109, 0,118,110, 95, 99,111,108,116,121,112,101, 0,110,111,105,115,101,100, +101,112,116,104, 0,110,111,105,115,101,116,121,112,101, 0,110,111,105,115,101, 98, 97,115,105,115, 0,110,111,105,115,101, 98, + 97,115,105,115, 50, 0,105,109, 97,102,108, 97,103, 0, 99,114,111,112,120,109,105,110, 0, 99,114,111,112,121,109,105,110, 0, + 99,114,111,112,120,109, 97,120, 0, 99,114,111,112,121,109, 97,120, 0,116,101,120,102,105,108,116,101,114, 0, 97,102,109, 97, +120, 0,120,114,101,112,101, 97,116, 0,121,114,101,112,101, 97,116, 0, 99,104,101, 99,107,101,114,100,105,115,116, 0,110, 97, + 98,108, 97, 0,105,117,115,101,114, 0, 42,110,111,100,101,116,114,101,101, 0, 42,112,108,117,103,105,110, 0, 42,101,110,118, + 0, 42,112,100, 0, 42,118,100, 0, 42,111,116, 0,117,115,101, 95,110,111,100,101,115, 0,108,111, 99, 91, 51, 93, 0,114,111, +116, 91, 51, 93, 0,109, 97,116, 91, 52, 93, 91, 52, 93, 0,109,105,110, 91, 51, 93, 0,109, 97,120, 91, 51, 93, 0, 99,111, 98, + 97, 0, 98,108,101,110,100, 95, 99,111,108,111,114, 91, 51, 93, 0, 98,108,101,110,100, 95,102, 97, 99,116,111,114, 0, 98,108, +101,110,100, 95,116,121,112,101, 0,112, 97,100, 91, 51, 93, 0,109,111,100,101, 0,116,111,116,101,120, 0,115,104,100,119,114, + 0,115,104,100,119,103, 0,115,104,100,119, 98, 0,115,104,100,119,112, 97,100, 0,101,110,101,114,103,121, 0,100,105,115,116, + 0,115,112,111,116,115,105,122,101, 0,115,112,111,116, 98,108,101,110,100, 0,104, 97,105,110,116, 0, 97,116,116, 49, 0, 97, +116,116, 50, 0, 42, 99,117,114,102, 97,108,108,111,102,102, 0,115,104, 97,100,115,112,111,116,115,105,122,101, 0, 98,105, 97, +115, 0,115,111,102,116, 0, 99,111,109,112,114,101,115,115,116,104,114,101,115,104, 0,112, 97,100, 53, 91, 51, 93, 0, 98,117, +102,115,105,122,101, 0,115, 97,109,112, 0, 98,117,102,102,101,114,115, 0,102,105,108,116,101,114,116,121,112,101, 0, 98,117, +102,102,108, 97,103, 0, 98,117,102,116,121,112,101, 0,114, 97,121, 95,115, 97,109,112, 0,114, 97,121, 95,115, 97,109,112,121, + 0,114, 97,121, 95,115, 97,109,112,122, 0,114, 97,121, 95,115, 97,109,112, 95,116,121,112,101, 0, 97,114,101, 97, 95,115,104, + 97,112,101, 0, 97,114,101, 97, 95,115,105,122,101, 0, 97,114,101, 97, 95,115,105,122,101,121, 0, 97,114,101, 97, 95,115,105, +122,101,122, 0, 97,100, 97,112,116, 95,116,104,114,101,115,104, 0,114, 97,121, 95,115, 97,109,112, 95,109,101,116,104,111,100, + 0,116,101,120, 97, 99,116, 0,115,104, 97,100,104, 97,108,111,115,116,101,112, 0,115,117,110, 95,101,102,102,101, 99,116, 95, +116,121,112,101, 0,115,107,121, 98,108,101,110,100,116,121,112,101, 0,104,111,114,105,122,111,110, 95, 98,114,105,103,104,116, +110,101,115,115, 0,115,112,114,101, 97,100, 0,115,117,110, 95, 98,114,105,103,104,116,110,101,115,115, 0,115,117,110, 95,115, +105,122,101, 0, 98, 97, 99,107,115, 99, 97,116,116,101,114,101,100, 95,108,105,103,104,116, 0,115,117,110, 95,105,110,116,101, +110,115,105,116,121, 0, 97,116,109, 95,116,117,114, 98,105,100,105,116,121, 0, 97,116,109, 95,105,110,115, 99, 97,116,116,101, +114,105,110,103, 95,102, 97, 99,116,111,114, 0, 97,116,109, 95,101,120,116,105,110, 99,116,105,111,110, 95,102, 97, 99,116,111, +114, 0, 97,116,109, 95,100,105,115,116, 97,110, 99,101, 95,102, 97, 99,116,111,114, 0,115,107,121, 98,108,101,110,100,102, 97, + 99, 0,115,107,121, 95,101,120,112,111,115,117,114,101, 0,115,107,121, 95, 99,111,108,111,114,115,112, 97, 99,101, 0,112, 97, +100, 52, 91, 54, 93, 0, 42,109,116,101,120, 91, 49, 56, 93, 0,112,114, 95,116,101,120,116,117,114,101, 0,112, 97,100, 54, 91, + 52, 93, 0,100,101,110,115,105,116,121, 0,101,109,105,115,115,105,111,110, 0,115, 99, 97,116,116,101,114,105,110,103, 0,114, +101,102,108,101, 99,116,105,111,110, 0,101,109,105,115,115,105,111,110, 95, 99,111,108, 91, 51, 93, 0,116,114, 97,110,115,109, +105,115,115,105,111,110, 95, 99,111,108, 91, 51, 93, 0,114,101,102,108,101, 99,116,105,111,110, 95, 99,111,108, 91, 51, 93, 0, +100,101,110,115,105,116,121, 95,115, 99, 97,108,101, 0,100,101,112,116,104, 95, 99,117,116,111,102,102, 0, 97,115,121,109,109, +101,116,114,121, 0,115,116,101,112,115,105,122,101, 95,116,121,112,101, 0,115,104, 97,100,101,102,108, 97,103, 0,115,104, 97, +100,101, 95,116,121,112,101, 0,112,114,101, 99, 97, 99,104,101, 95,114,101,115,111,108,117,116,105,111,110, 0,115,116,101,112, +115,105,122,101, 0,109,115, 95,100,105,102,102, 0,109,115, 95,105,110,116,101,110,115,105,116,121, 0,109,115, 95,115,112,114, +101, 97,100, 0, 97,108,112,104, 97, 95, 98,108,101,110,100, 0,102, 97, 99,101, 95,111,114,105,101,110,116, 97,116,105,111,110, + 0,109, 97,116,101,114,105, 97,108, 95,116,121,112,101, 0,115,112,101, 99,114, 0,115,112,101, 99,103, 0,115,112,101, 99, 98, + 0,109,105,114,114, 0,109,105,114,103, 0,109,105,114, 98, 0, 97,109, 98,114, 0, 97,109, 98, 98, 0, 97,109, 98,103, 0, 97, +109, 98, 0,101,109,105,116, 0, 97,110,103, 0,115,112,101, 99,116,114, 97, 0,114, 97,121, 95,109,105,114,114,111,114, 0, 97, +108,112,104, 97, 0,114,101,102, 0,115,112,101, 99, 0,122,111,102,102,115, 0, 97,100,100, 0,116,114, 97,110,115,108,117, 99, +101,110, 99,121, 0,118,111,108, 0,103, 97,109,101, 0,102,114,101,115,110,101,108, 95,109,105,114, 0,102,114,101,115,110,101, +108, 95,109,105,114, 95,105, 0,102,114,101,115,110,101,108, 95,116,114, 97, 0,102,114,101,115,110,101,108, 95,116,114, 97, 95, +105, 0,102,105,108,116,101,114, 0,116,120, 95,108,105,109,105,116, 0,116,120, 95,102, 97,108,108,111,102,102, 0,114, 97,121, + 95,100,101,112,116,104, 0,114, 97,121, 95,100,101,112,116,104, 95,116,114, 97, 0,104, 97,114, 0,115,101,101,100, 49, 0,115, +101,101,100, 50, 0,103,108,111,115,115, 95,109,105,114, 0,103,108,111,115,115, 95,116,114, 97, 0,115, 97,109,112, 95,103,108, +111,115,115, 95,109,105,114, 0,115, 97,109,112, 95,103,108,111,115,115, 95,116,114, 97, 0, 97,100, 97,112,116, 95,116,104,114, +101,115,104, 95,109,105,114, 0, 97,100, 97,112,116, 95,116,104,114,101,115,104, 95,116,114, 97, 0, 97,110,105,115,111, 95,103, +108,111,115,115, 95,109,105,114, 0,100,105,115,116, 95,109,105,114, 0,102, 97,100,101,116,111, 95,109,105,114, 0,115,104, 97, +100,101, 95,102,108, 97,103, 0,109,111,100,101, 95,108, 0,102,108, 97,114,101, 99, 0,115,116, 97,114, 99, 0,108,105,110,101, + 99, 0,114,105,110,103, 99, 0,104, 97,115,105,122,101, 0,102,108, 97,114,101,115,105,122,101, 0,115,117, 98,115,105,122,101, + 0,102,108, 97,114,101, 98,111,111,115,116, 0,115,116,114, 97,110,100, 95,115,116, 97, 0,115,116,114, 97,110,100, 95,101,110, +100, 0,115,116,114, 97,110,100, 95,101, 97,115,101, 0,115,116,114, 97,110,100, 95,115,117,114,102,110,111,114, 0,115,116,114, + 97,110,100, 95,109,105,110, 0,115,116,114, 97,110,100, 95,119,105,100,116,104,102, 97,100,101, 0,115,116,114, 97,110,100, 95, +117,118,110, 97,109,101, 91, 54, 52, 93, 0,115, 98,105, 97,115, 0,108, 98,105, 97,115, 0,115,104, 97,100, 95, 97,108,112,104, + 97, 0,115,101,112,116,101,120, 0,114,103, 98,115,101,108, 0,112,114, 95,116,121,112,101, 0,112,114, 95, 98, 97, 99,107, 0, +112,114, 95,108, 97,109,112, 0,109,108, 95,102,108, 97,103, 0,100,105,102,102, 95,115,104, 97,100,101,114, 0,115,112,101, 99, + 95,115,104, 97,100,101,114, 0,114,111,117,103,104,110,101,115,115, 0,114,101,102,114, 97, 99, 0,112, 97,114, 97,109, 91, 52, + 93, 0,114,109,115, 0,100, 97,114,107,110,101,115,115, 0, 42,114, 97,109,112, 95, 99,111,108, 0, 42,114, 97,109,112, 95,115, +112,101, 99, 0,114, 97,109,112,105,110, 95, 99,111,108, 0,114, 97,109,112,105,110, 95,115,112,101, 99, 0,114, 97,109,112, 98, +108,101,110,100, 95, 99,111,108, 0,114, 97,109,112, 98,108,101,110,100, 95,115,112,101, 99, 0,114, 97,109,112, 95,115,104,111, +119, 0,112, 97,100, 51, 0,114, 97,109,112,102, 97, 99, 95, 99,111,108, 0,114, 97,109,112,102, 97, 99, 95,115,112,101, 99, 0, + 42,103,114,111,117,112, 0,102,114,105, 99,116,105,111,110, 0,102,104, 0,114,101,102,108,101, 99,116, 0,102,104,100,105,115, +116, 0,120,121,102,114,105, 99,116, 0,100,121,110, 97,109,111,100,101, 0,115,115,115, 95,114, 97,100,105,117,115, 91, 51, 93, + 0,115,115,115, 95, 99,111,108, 91, 51, 93, 0,115,115,115, 95,101,114,114,111,114, 0,115,115,115, 95,115, 99, 97,108,101, 0, +115,115,115, 95,105,111,114, 0,115,115,115, 95, 99,111,108,102, 97, 99, 0,115,115,115, 95,116,101,120,102, 97, 99, 0,115,115, +115, 95,102,114,111,110,116, 0,115,115,115, 95, 98, 97, 99,107, 0,115,115,115, 95,102,108, 97,103, 0,115,115,115, 95,112,114, +101,115,101,116, 0,109, 97,112,116,111, 95,116,101,120,116,117,114,101,100, 0,115,104, 97,100,111,119,111,110,108,121, 95,102, +108, 97,103, 0,105,110,100,101,120, 0,103,112,117,109, 97,116,101,114,105, 97,108, 0, 42, 98, 98, 0,115,101,108, 99,111,108, + 49, 0,115,101,108, 99,111,108, 50, 0,113,117, 97,116, 91, 52, 93, 0,101,120,112,120, 0,101,120,112,121, 0,101,120,112,122, + 0,114, 97,100, 0,114, 97,100, 50, 0,115, 0, 42,109, 97,116, 0, 42,105,109, 97,116, 0,101,108,101,109,115, 0,100,105,115, +112, 0, 42,101,100,105,116,101,108,101,109,115, 0, 42, 42,109, 97,116, 0,102,108, 97,103, 50, 0,116,111,116, 99,111,108, 0, +119,105,114,101,115,105,122,101, 0,114,101,110,100,101,114,115,105,122,101, 0,116,104,114,101,115,104, 0, 42,108, 97,115,116, +101,108,101,109, 0,118,101, 99, 91, 51, 93, 91, 51, 93, 0, 97,108,102, 97, 0,119,101,105,103,104,116, 0,104, 49, 0,104, 50, + 0,102, 49, 0,102, 50, 0,102, 51, 0,104,105,100,101, 0,118,101, 99, 91, 52, 93, 0,109, 97,116, 95,110,114, 0,112,110,116, +115,117, 0,112,110,116,115,118, 0,114,101,115,111,108,117, 0,114,101,115,111,108,118, 0,111,114,100,101,114,117, 0,111,114, +100,101,114,118, 0,102,108, 97,103,117, 0,102,108, 97,103,118, 0, 42,107,110,111,116,115,117, 0, 42,107,110,111,116,115,118, + 0,116,105,108,116, 95,105,110,116,101,114,112, 0,114, 97,100,105,117,115, 95,105,110,116,101,114,112, 0, 99,104, 97,114,105, +100,120, 0,107,101,114,110, 0,119, 0,104, 0,110,117,114, 98,115, 0, 42,107,101,121,105,110,100,101,120, 0,115,104, 97,112, +101,110,114, 0,110,117,114, 98, 0, 42,101,100,105,116,110,117,114, 98, 0, 42, 98,101,118,111, 98,106, 0, 42,116, 97,112,101, +114,111, 98,106, 0, 42,116,101,120,116,111,110, 99,117,114,118,101, 0, 42,112, 97,116,104, 0, 42,107,101,121, 0, 98,101,118, + 0,100,114, 97,119,102,108, 97,103, 0,116,119,105,115,116, 95,109,111,100,101, 0,116,119,105,115,116, 95,115,109,111,111,116, +104, 0,115,109, 97,108,108, 99, 97,112,115, 95,115, 99, 97,108,101, 0,112, 97,116,104,108,101,110, 0, 98,101,118,114,101,115, +111,108, 0,119,105,100,116,104, 0,101,120,116, 49, 0,101,120,116, 50, 0,114,101,115,111,108,117, 95,114,101,110, 0,114,101, +115,111,108,118, 95,114,101,110, 0, 97, 99,116,110,117, 0, 42,108, 97,115,116,115,101,108, 0,115,112, 97, 99,101,109,111,100, +101, 0,115,112, 97, 99,105,110,103, 0,108,105,110,101,100,105,115,116, 0,115,104,101, 97,114, 0,102,115,105,122,101, 0,119, +111,114,100,115,112, 97, 99,101, 0,117,108,112,111,115, 0,117,108,104,101,105,103,104,116, 0,120,111,102, 0,121,111,102, 0, +108,105,110,101,119,105,100,116,104, 0, 42,115,116,114, 0, 42,115,101,108, 98,111,120,101,115, 0, 42,101,100,105,116,102,111, +110,116, 0,102, 97,109,105,108,121, 91, 50, 52, 93, 0, 42,118,102,111,110,116, 0, 42,118,102,111,110,116, 98, 0, 42,118,102, +111,110,116,105, 0, 42,118,102,111,110,116, 98,105, 0,115,101,112, 99,104, 97,114, 0,116,111,116, 98,111,120, 0, 97, 99,116, + 98,111,120, 0, 42,116, 98, 0,115,101,108,115,116, 97,114,116, 0,115,101,108,101,110,100, 0, 42,115,116,114,105,110,102,111, + 0, 99,117,114,105,110,102,111, 0, 42,109,115,101,108,101, 99,116, 0, 42,109,112,111,108,121, 0, 42,109,116,112,111,108,121, + 0, 42,109,108,111,111,112, 0, 42,109,108,111,111,112,117,118, 0, 42,109,108,111,111,112, 99,111,108, 0, 42,109,102, 97, 99, +101, 0, 42,109,116,102, 97, 99,101, 0, 42,116,102, 97, 99,101, 0, 42,109,118,101,114,116, 0, 42,109,101,100,103,101, 0, 42, +100,118,101,114,116, 0, 42,109, 99,111,108, 0, 42,109,115,116,105, 99,107,121, 0, 42,116,101,120, 99,111,109,101,115,104, 0, + 42,101,100,105,116, 95, 98,116,109,101,115,104, 0,118,100, 97,116, 97, 0,101,100, 97,116, 97, 0,102,100, 97,116, 97, 0,112, +100, 97,116, 97, 0,108,100, 97,116, 97, 0,116,111,116,101,100,103,101, 0,116,111,116,102, 97, 99,101, 0,116,111,116,115,101, +108,101, 99,116, 0,116,111,116,112,111,108,121, 0,116,111,116,108,111,111,112, 0, 97, 99,116, 95,102, 97, 99,101, 0,115,109, +111,111,116,104,114,101,115,104, 0,115,117, 98,100,105,118, 0,115,117, 98,100,105,118,114, 0,115,117, 98,115,117,114,102,116, +121,112,101, 0,101,100,105,116,102,108, 97,103, 0, 42,109,114, 0, 42,116,112, 97,103,101, 0,117,118, 91, 52, 93, 91, 50, 93, + 0, 99,111,108, 91, 52, 93, 0,116,114, 97,110,115,112, 0,116,105,108,101, 0,117,110,119,114, 97,112, 0,118, 49, 0,118, 50, + 0,118, 51, 0,118, 52, 0,101,100, 99,111,100,101, 0, 99,114,101, 97,115,101, 0, 98,119,101,105,103,104,116, 0,100,101,102, + 95,110,114, 0, 42,100,119, 0,116,111,116,119,101,105,103,104,116, 0, 99,111, 91, 51, 93, 0,110,111, 91, 51, 93, 0,108,111, +111,112,115,116, 97,114,116, 0,118, 0,101, 0,117,118, 91, 50, 93, 0, 99,111, 91, 50, 93, 0,102, 0,105, 0,115, 91, 50, 53, + 54, 93, 0,116,111,116,100,105,115,112, 0,108,101,118,101,108, 0, 40, 42,100,105,115,112,115, 41, 40, 41, 0, 42,104,105,100, +100,101,110, 0,118, 91, 52, 93, 0,109,105,100, 0,112, 97,100, 91, 50, 93, 0,118, 91, 50, 93, 0, 42,102, 97, 99,101,115, 0, + 42, 99,111,108,102, 97, 99,101,115, 0, 42,101,100,103,101,115, 0, 42,118,101,114,116,115, 0,108,101,118,101,108,115, 0,108, +101,118,101,108, 95, 99,111,117,110,116, 0, 99,117,114,114,101,110,116, 0,110,101,119,108,118,108, 0,101,100,103,101,108,118, +108, 0,112,105,110,108,118,108, 0,114,101,110,100,101,114,108,118,108, 0,117,115,101, 95, 99,111,108, 0, 42,101,100,103,101, + 95,102,108, 97,103,115, 0, 42,101,100,103,101, 95, 99,114,101, 97,115,101,115, 0,115,116, 97, 99,107,105,110,100,101,120, 0, + 42,101,114,114,111,114, 0,109,111,100,105,102,105,101,114, 0, 42,116,101,120,116,117,114,101, 0, 42,109, 97,112, 95,111, 98, +106,101, 99,116, 0,117,118,108, 97,121,101,114, 95,110, 97,109,101, 91, 54, 52, 93, 0,117,118,108, 97,121,101,114, 95,116,109, +112, 0,116,101,120,109, 97,112,112,105,110,103, 0,115,117, 98,100,105,118, 84,121,112,101, 0,114,101,110,100,101,114, 76,101, +118,101,108,115, 0, 42,101,109, 67, 97, 99,104,101, 0, 42,109, 67, 97, 99,104,101, 0,115,116,114,101,110,103,116,104, 0,100, +101,102, 97,120,105,115, 0,112, 97,100, 91, 54, 93, 0,108,101,110,103,116,104, 0,114, 97,110,100,111,109,105,122,101, 0,115, +101,101,100, 0, 42,111, 98, 95, 97,114,109, 0, 42,115,116, 97,114,116, 95, 99, 97,112, 0, 42,101,110,100, 95, 99, 97,112, 0, + 42, 99,117,114,118,101, 95,111, 98, 0, 42,111,102,102,115,101,116, 95,111, 98, 0,111,102,102,115,101,116, 91, 51, 93, 0,115, + 99, 97,108,101, 91, 51, 93, 0,109,101,114,103,101, 95,100,105,115,116, 0,102,105,116, 95,116,121,112,101, 0,111,102,102,115, +101,116, 95,116,121,112,101, 0, 99,111,117,110,116, 0, 97,120,105,115, 0,116,111,108,101,114, 97,110, 99,101, 0, 42,109,105, +114,114,111,114, 95,111, 98, 0,115,112,108,105,116, 95, 97,110,103,108,101, 0,118, 97,108,117,101, 0,114,101,115, 0,118, 97, +108, 95,102,108, 97,103,115, 0,108,105,109, 95,102,108, 97,103,115, 0,101, 95,102,108, 97,103,115, 0, 98,101,118,101,108, 95, + 97,110,103,108,101, 0,100,101,102,103,114,112, 95,110, 97,109,101, 91, 54, 52, 93, 0, 42,100,111,109, 97,105,110, 0, 42,102, +108,111,119, 0, 42, 99,111,108,108, 0,116,105,109,101, 0,100,105,114,101, 99,116,105,111,110, 0,109,105,100,108,101,118,101, +108, 0, 42,112,114,111,106,101, 99,116,111,114,115, 91, 49, 48, 93, 0, 42,105,109, 97,103,101, 0,110,117,109, 95,112,114,111, +106,101, 99,116,111,114,115, 0, 97,115,112,101, 99,116,120, 0, 97,115,112,101, 99,116,121, 0,115, 99, 97,108,101,120, 0,115, + 99, 97,108,101,121, 0,112,101,114, 99,101,110,116, 0,102, 97, 99,101, 67,111,117,110,116, 0,102, 97, 99, 0,114,101,112,101, + 97,116, 0, 42,111, 98,106,101, 99,116, 99,101,110,116,101,114, 0,115,116, 97,114,116,120, 0,115,116, 97,114,116,121, 0,104, +101,105,103,104,116, 0,110, 97,114,114,111,119, 0,115,112,101,101,100, 0,100, 97,109,112, 0,102, 97,108,108,111,102,102, 0, +116,105,109,101,111,102,102,115, 0,108,105,102,101,116,105,109,101, 0,100,101,102,111,114,109,102,108, 97,103, 0,109,117,108, +116,105, 0, 42,112,114,101,118, 67,111,115, 0,115,117, 98,116, 97,114,103,101,116, 91, 54, 52, 93, 0,112, 97,114,101,110,116, +105,110,118, 91, 52, 93, 91, 52, 93, 0, 99,101,110,116, 91, 51, 93, 0, 42,105,110,100,101,120, 97,114, 0,116,111,116,105,110, +100,101,120, 0,102,111,114, 99,101, 0, 42, 99,108,111,116,104, 79, 98,106,101, 99,116, 0, 42,115,105,109, 95,112, 97,114,109, +115, 0, 42, 99,111,108,108, 95,112, 97,114,109,115, 0, 42,112,111,105,110,116, 95, 99, 97, 99,104,101, 0,112,116, 99, 97, 99, +104,101,115, 0, 42,120, 0, 42,120,110,101,119, 0, 42,120,111,108,100, 0, 42, 99,117,114,114,101,110,116, 95,120,110,101,119, + 0, 42, 99,117,114,114,101,110,116, 95,120, 0, 42, 99,117,114,114,101,110,116, 95,118, 0, 42,109,102, 97, 99,101,115, 0,110, +117,109,118,101,114,116,115, 0,110,117,109,102, 97, 99,101,115, 0,116,105,109,101, 95,120, 0,116,105,109,101, 95,120,110,101, +119, 0, 42, 98,118,104,116,114,101,101, 0, 42,118, 0, 42,100,109, 0, 99,102,114, 97, 0,111,112,101,114, 97,116,105,111,110, + 0,118,101,114,116,101,120, 0,116,111,116,105,110,102,108,117,101,110, 99,101, 0,103,114,105,100,115,105,122,101, 0, 42, 98, +105,110,100,105,110,102,108,117,101,110, 99,101,115, 0, 42, 98,105,110,100,111,102,102,115,101,116,115, 0, 42, 98,105,110,100, + 99, 97,103,101, 99,111,115, 0,116,111,116, 99, 97,103,101,118,101,114,116, 0, 42,100,121,110,103,114,105,100, 0, 42,100,121, +110,105,110,102,108,117,101,110, 99,101,115, 0, 42,100,121,110,118,101,114,116,115, 0, 42,112, 97,100, 50, 0,100,121,110,103, +114,105,100,115,105,122,101, 0,100,121,110, 99,101,108,108,109,105,110, 91, 51, 93, 0,100,121,110, 99,101,108,108,119,105,100, +116,104, 0, 98,105,110,100,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 42, 98,105,110,100,119,101,105,103,104,116,115, 0, 42, 98, +105,110,100, 99,111,115, 0, 40, 42, 98,105,110,100,102,117,110, 99, 41, 40, 41, 0, 42,112,115,121,115, 0,116,111,116,100,109, +118,101,114,116, 0,116,111,116,100,109,101,100,103,101, 0,116,111,116,100,109,102, 97, 99,101, 0,112,111,115,105,116,105,111, +110, 0,114, 97,110,100,111,109, 95,112,111,115,105,116,105,111,110, 0, 42,102, 97, 99,101,112, 97, 0,118,103,114,111,117,112, + 0,112,114,111,116,101, 99,116, 0,108,118,108, 0,115, 99,117,108,112,116,108,118,108, 0,116,111,116,108,118,108, 0,115,105, +109,112,108,101, 0, 42,102,115,115, 0, 42,116, 97,114,103,101,116, 0, 42, 97,117,120, 84, 97,114,103,101,116, 0,118,103,114, +111,117,112, 95,110, 97,109,101, 91, 54, 52, 93, 0,107,101,101,112, 68,105,115,116, 0,115,104,114,105,110,107, 84,121,112,101, + 0,115,104,114,105,110,107, 79,112,116,115, 0,112,114,111,106, 65,120,105,115, 0,115,117, 98,115,117,114,102, 76,101,118,101, +108,115, 0, 42,111,114,105,103,105,110, 0,102, 97, 99,116,111,114, 0,108,105,109,105,116, 91, 50, 93, 0,111,114,105,103,105, +110, 79,112,116,115, 0,111,102,102,115,101,116, 95,102, 97, 99, 0,111,102,102,115,101,116, 95,102, 97, 99, 95,118,103, 0, 99, +114,101, 97,115,101, 95,105,110,110,101,114, 0, 99,114,101, 97,115,101, 95,111,117,116,101,114, 0, 99,114,101, 97,115,101, 95, +114,105,109, 0,109, 97,116, 95,111,102,115, 0,109, 97,116, 95,111,102,115, 95,114,105,109, 0, 42,111, 98, 95, 97,120,105,115, + 0,115,116,101,112,115, 0,114,101,110,100,101,114, 95,115,116,101,112,115, 0,105,116,101,114, 0,115, 99,114,101,119, 95,111, +102,115, 0, 97,110,103,108,101, 0, 42,111, 99,101, 97,110, 0, 42,111, 99,101, 97,110, 99, 97, 99,104,101, 0,114,101,115,111, +108,117,116,105,111,110, 0,115,112, 97,116,105, 97,108, 95,115,105,122,101, 0,119,105,110,100, 95,118,101,108,111, 99,105,116, +121, 0,115,109, 97,108,108,101,115,116, 95,119, 97,118,101, 0,119, 97,118,101, 95, 97,108,105,103,110,109,101,110,116, 0,119, + 97,118,101, 95,100,105,114,101, 99,116,105,111,110, 0,119, 97,118,101, 95,115, 99, 97,108,101, 0, 99,104,111,112, 95, 97,109, +111,117,110,116, 0,102,111, 97,109, 95, 99,111,118,101,114, 97,103,101, 0, 98, 97,107,101,115,116, 97,114,116, 0, 98, 97,107, +101,101,110,100, 0, 99, 97, 99,104,101,112, 97,116,104, 91, 49, 48, 50, 52, 93, 0,102,111, 97,109,108, 97,121,101,114,110, 97, +109,101, 91, 54, 52, 93, 0, 99, 97, 99,104,101,100, 0,103,101,111,109,101,116,114,121, 95,109,111,100,101, 0,114,101,102,114, +101,115,104, 0,114,101,112,101, 97,116, 95,120, 0,114,101,112,101, 97,116, 95,121, 0,102,111, 97,109, 95,102, 97,100,101, 0, + 42,111, 98,106,101, 99,116, 95,102,114,111,109, 0, 42,111, 98,106,101, 99,116, 95,116,111, 0,102, 97,108,108,111,102,102, 95, +114, 97,100,105,117,115, 0,101,100,105,116, 95,102,108, 97,103,115, 0,100,101,102, 97,117,108,116, 95,119,101,105,103,104,116, + 0, 42, 99,109, 97,112, 95, 99,117,114,118,101, 0, 97,100,100, 95,116,104,114,101,115,104,111,108,100, 0,114,101,109, 95,116, +104,114,101,115,104,111,108,100, 0,109, 97,115,107, 95, 99,111,110,115,116, 97,110,116, 0,109, 97,115,107, 95,100,101,102,103, +114,112, 95,110, 97,109,101, 91, 54, 52, 93, 0,109, 97,115,107, 95,116,101,120, 95,117,115,101, 95, 99,104, 97,110,110,101,108, + 0, 42,109, 97,115,107, 95,116,101,120,116,117,114,101, 0, 42,109, 97,115,107, 95,116,101,120, 95,109, 97,112, 95,111, 98,106, + 0,109, 97,115,107, 95,116,101,120, 95,109, 97,112,112,105,110,103, 0,109, 97,115,107, 95,116,101,120, 95,117,118,108, 97,121, +101,114, 95,110, 97,109,101, 91, 54, 52, 93, 0,112, 97,100, 95,105, 49, 0,100,101,102,103,114,112, 95,110, 97,109,101, 95, 97, + 91, 54, 52, 93, 0,100,101,102,103,114,112, 95,110, 97,109,101, 95, 98, 91, 54, 52, 93, 0,100,101,102, 97,117,108,116, 95,119, +101,105,103,104,116, 95, 97, 0,100,101,102, 97,117,108,116, 95,119,101,105,103,104,116, 95, 98, 0,109,105,120, 95,109,111,100, +101, 0,109,105,120, 95,115,101,116, 0,112, 97,100, 95, 99, 49, 91, 54, 93, 0,112,114,111,120,105,109,105,116,121, 95,109,111, +100,101, 0,112,114,111,120,105,109,105,116,121, 95,102,108, 97,103,115, 0, 42,112,114,111,120,105,109,105,116,121, 95,111, 98, + 95,116, 97,114,103,101,116, 0,109,105,110, 95,100,105,115,116, 0,109, 97,120, 95,100,105,115,116, 0,112, 97,100, 95,115, 49, + 0, 42, 99, 97,110,118, 97,115, 0, 42, 98,114,117,115,104, 0,116,104,114,101,115,104,111,108,100, 0,115, 99, 97,108,101, 0, +104,101,114,109,105,116,101, 95,110,117,109, 0, 42,108, 97,116,116, 0,112,110,116,115,119, 0,111,112,110,116,115,117, 0,111, +112,110,116,115,118, 0,111,112,110,116,115,119, 0,116,121,112,101,117, 0,116,121,112,101,118, 0,116,121,112,101,119, 0,102, +117, 0,102,118, 0,102,119, 0,100,117, 0,100,118, 0,100,119, 0, 42,100,101,102, 0, 42,108, 97,116,116,105, 99,101,100, 97, +116, 97, 0,108, 97,116,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 42,101,100,105,116,108, 97,116,116, 0,118,101, 99, 91, 56, 93, + 91, 51, 93, 0, 42,115, 99,117,108,112,116, 0,112, 97,114,116,121,112,101, 0,112, 97,114, 49, 0,112, 97,114, 50, 0,112, 97, +114, 51, 0,112, 97,114,115,117, 98,115,116,114, 91, 54, 52, 93, 0, 42,116,114, 97, 99,107, 0, 42,112,114,111,120,121, 0, 42, +112,114,111,120,121, 95,103,114,111,117,112, 0, 42,112,114,111,120,121, 95,102,114,111,109, 0, 42, 97, 99,116,105,111,110, 0, + 42,112,111,115,101,108,105, 98, 0, 42,112,111,115,101, 0, 42,103,112,100, 0, 97,118,115, 0, 42,109,112, 97,116,104, 0, 99, +111,110,115,116,114, 97,105,110,116, 67,104, 97,110,110,101,108,115, 0,101,102,102,101, 99,116, 0,100,101,102, 98, 97,115,101, + 0,109,111,100,105,102,105,101,114,115, 0,114,101,115,116,111,114,101, 95,109,111,100,101, 0, 42,109, 97,116, 98,105,116,115, + 0, 97, 99,116, 99,111,108, 0,100,108,111, 99, 91, 51, 93, 0,111,114,105,103, 91, 51, 93, 0,100,115,105,122,101, 91, 51, 93, + 0,100,115, 99, 97,108,101, 91, 51, 93, 0,100,114,111,116, 91, 51, 93, 0,100,113,117, 97,116, 91, 52, 93, 0,114,111,116, 65, +120,105,115, 91, 51, 93, 0,100,114,111,116, 65,120,105,115, 91, 51, 93, 0,114,111,116, 65,110,103,108,101, 0,100,114,111,116, + 65,110,103,108,101, 0,111, 98,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 99,111,110,115,116,105,110,118, 91, 52, 93, 91, 52, 93, + 0,105,109, 97,116, 95,114,101,110, 91, 52, 93, 91, 52, 93, 0,108, 97,121, 0,112, 97,100, 54, 0, 99,111,108, 98,105,116,115, + 0,116,114, 97,110,115,102,108, 97,103, 0,112,114,111,116,101, 99,116,102,108, 97,103, 0,116,114, 97, 99,107,102,108, 97,103, + 0,117,112,102,108, 97,103, 0,110,108, 97,102,108, 97,103, 0,105,112,111,102,108, 97,103, 0,115, 99, 97,102,108, 97,103, 0, +115, 99, 97,118,105,115,102,108, 97,103, 0,112, 97,100, 53, 0,100,117,112,111,110, 0,100,117,112,111,102,102, 0,100,117,112, +115,116, 97, 0,100,117,112,101,110,100, 0,115,102, 0,109, 97,115,115, 0,100, 97,109,112,105,110,103, 0,105,110,101,114,116, +105, 97, 0,102,111,114,109,102, 97, 99,116,111,114, 0,114,100, 97,109,112,105,110,103, 0,109, 97,114,103,105,110, 0,109, 97, +120, 95,118,101,108, 0,109,105,110, 95,118,101,108, 0,109, 95, 99,111,110,116, 97, 99,116, 80,114,111, 99,101,115,115,105,110, +103, 84,104,114,101,115,104,111,108,100, 0,111, 98,115,116, 97, 99,108,101, 82, 97,100, 0,114,111,116,109,111,100,101, 0, 98, +111,117,110,100,116,121,112,101, 0, 99,111,108,108,105,115,105,111,110, 95, 98,111,117,110,100,116,121,112,101, 0,114,101,115, +116,114,105, 99,116,102,108, 97,103, 0,100,116, 0,101,109,112,116,121, 95,100,114, 97,119,116,121,112,101, 0,101,109,112,116, +121, 95,100,114, 97,119,115,105,122,101, 0,100,117,112,102, 97, 99,101,115, 99, 97, 0,112,114,111,112, 0,115,101,110,115,111, +114,115, 0, 99,111,110,116,114,111,108,108,101,114,115, 0, 97, 99,116,117, 97,116,111,114,115, 0, 98, 98,115,105,122,101, 91, + 51, 93, 0, 97, 99,116,100,101,102, 0,103, 97,109,101,102,108, 97,103, 0,103, 97,109,101,102,108, 97,103, 50, 0, 42, 98,115, +111,102,116, 0,115,111,102,116,102,108, 97,103, 0, 97,110,105,115,111,116,114,111,112,105, 99, 70,114,105, 99,116,105,111,110, + 91, 51, 93, 0, 99,111,110,115,116,114, 97,105,110,116,115, 0,110,108, 97,115,116,114,105,112,115, 0,104,111,111,107,115, 0, +112, 97,114,116,105, 99,108,101,115,121,115,116,101,109, 0, 42,115,111,102,116, 0, 42,100,117,112, 95,103,114,111,117,112, 0, + 98,111,100,121, 95,116,121,112,101, 0,115,104, 97,112,101,102,108, 97,103, 0, 42,102,108,117,105,100,115,105,109, 83,101,116, +116,105,110,103,115, 0, 42,100,101,114,105,118,101,100, 68,101,102,111,114,109, 0, 42,100,101,114,105,118,101,100, 70,105,110, + 97,108, 0,108, 97,115,116, 68, 97,116, 97, 77, 97,115,107, 0, 99,117,115,116,111,109,100, 97,116, 97, 95,109, 97,115,107, 0, +115,116, 97,116,101, 0,105,110,105,116, 95,115,116, 97,116,101, 0,103,112,117,108, 97,109,112, 0,112, 99, 95,105,100,115, 0, + 42,100,117,112,108,105,108,105,115,116, 0,105,109, 97, 95,111,102,115, 91, 50, 93, 0, 99,117,114,105,110,100,101,120, 0, 97, + 99,116,105,118,101, 0,111,114,105,103,108, 97,121, 0,111,109, 97,116, 91, 52, 93, 91, 52, 93, 0,111,114, 99,111, 91, 51, 93, + 0,110,111, 95,100,114, 97,119, 0, 97,110,105,109, 97,116,101,100, 0,100,101,102,108,101, 99,116, 0,102,111,114, 99,101,102, +105,101,108,100, 0,115,104, 97,112,101, 0,116,101,120, 95,109,111,100,101, 0,107,105,110,107, 0,107,105,110,107, 95, 97,120, +105,115, 0,122,100,105,114, 0,102, 95,115,116,114,101,110,103,116,104, 0,102, 95,100, 97,109,112, 0,102, 95,102,108,111,119, + 0,102, 95,115,105,122,101, 0,102, 95,112,111,119,101,114, 0,109, 97,120,100,105,115,116, 0,109,105,110,100,105,115,116, 0, +102, 95,112,111,119,101,114, 95,114, 0,109, 97,120,114, 97,100, 0,109,105,110,114, 97,100, 0,112,100,101,102, 95,100, 97,109, +112, 0,112,100,101,102, 95,114,100, 97,109,112, 0,112,100,101,102, 95,112,101,114,109, 0,112,100,101,102, 95,102,114,105, 99, +116, 0,112,100,101,102, 95,114,102,114,105, 99,116, 0,112,100,101,102, 95,115,116,105, 99,107,110,101,115,115, 0, 97, 98,115, +111,114,112,116,105,111,110, 0,112,100,101,102, 95,115, 98,100, 97,109,112, 0,112,100,101,102, 95,115, 98,105,102,116, 0,112, +100,101,102, 95,115, 98,111,102,116, 0, 99,108,117,109,112, 95,102, 97, 99, 0, 99,108,117,109,112, 95,112,111,119, 0,107,105, +110,107, 95,102,114,101,113, 0,107,105,110,107, 95,115,104, 97,112,101, 0,107,105,110,107, 95, 97,109,112, 0,102,114,101,101, + 95,101,110,100, 0,116,101,120, 95,110, 97, 98,108, 97, 0, 42,114,110,103, 0,102, 95,110,111,105,115,101, 0,119,101,105,103, +104,116, 91, 49, 51, 93, 0,103,108,111, 98, 97,108, 95,103,114, 97,118,105,116,121, 0,114,116, 91, 51, 93, 0,116,111,116,100, + 97,116, 97, 0,102,114, 97,109,101, 0,116,111,116,112,111,105,110,116, 0,100, 97,116, 97, 95,116,121,112,101,115, 0, 42,100, + 97,116, 97, 91, 56, 93, 0, 42, 99,117,114, 91, 56, 93, 0,101,120,116,114, 97,100, 97,116, 97, 0,115,116,101,112, 0,115,105, +109,102,114, 97,109,101, 0,115,116, 97,114,116,102,114, 97,109,101, 0,101,110,100,102,114, 97,109,101, 0,101,100,105,116,102, +114, 97,109,101, 0,108, 97,115,116, 95,101,120, 97, 99,116, 0,108, 97,115,116, 95,118, 97,108,105,100, 0, 99,111,109,112,114, +101,115,115,105,111,110, 0,112,114,101,118, 95,110, 97,109,101, 91, 54, 52, 93, 0,105,110,102,111, 91, 54, 52, 93, 0,112, 97, +116,104, 91, 49, 48, 50, 52, 93, 0, 42, 99, 97, 99,104,101,100, 95,102,114, 97,109,101,115, 0,109,101,109, 95, 99, 97, 99,104, +101, 0, 42,101,100,105,116, 0, 40, 42,102,114,101,101, 95,101,100,105,116, 41, 40, 41, 0,108,105,110, 83,116,105,102,102, 0, + 97,110,103, 83,116,105,102,102, 0,118,111,108,117,109,101, 0,118,105,116,101,114, 97,116,105,111,110,115, 0,112,105,116,101, +114, 97,116,105,111,110,115, 0,100,105,116,101,114, 97,116,105,111,110,115, 0, 99,105,116,101,114, 97,116,105,111,110,115, 0, +107, 83, 82, 72, 82, 95, 67, 76, 0,107, 83, 75, 72, 82, 95, 67, 76, 0,107, 83, 83, 72, 82, 95, 67, 76, 0,107, 83, 82, 95, 83, + 80, 76, 84, 95, 67, 76, 0,107, 83, 75, 95, 83, 80, 76, 84, 95, 67, 76, 0,107, 83, 83, 95, 83, 80, 76, 84, 95, 67, 76, 0,107, + 86, 67, 70, 0,107, 68, 80, 0,107, 68, 71, 0,107, 76, 70, 0,107, 80, 82, 0,107, 86, 67, 0,107, 68, 70, 0,107, 77, 84, 0, +107, 67, 72, 82, 0,107, 75, 72, 82, 0,107, 83, 72, 82, 0,107, 65, 72, 82, 0, 99,111,108,108,105,115,105,111,110,102,108, 97, +103,115, 0,110,117,109, 99,108,117,115,116,101,114,105,116,101,114, 97,116,105,111,110,115, 0,119,101,108,100,105,110,103, 0, +116,111,116,115,112,114,105,110,103, 0, 42, 98,112,111,105,110,116, 0, 42, 98,115,112,114,105,110,103, 0,109,115,103, 95,108, +111, 99,107, 0,109,115,103, 95,118, 97,108,117,101, 0,110,111,100,101,109, 97,115,115, 0,110, 97,109,101,100, 86, 71, 95, 77, + 97,115,115, 91, 54, 52, 93, 0,103,114, 97,118, 0,109,101,100,105, 97,102,114,105, 99,116, 0,114,107,108,105,109,105,116, 0, +112,104,121,115,105, 99,115, 95,115,112,101,101,100, 0,103,111, 97,108,115,112,114,105,110,103, 0,103,111, 97,108,102,114,105, + 99,116, 0,109,105,110,103,111, 97,108, 0,109, 97,120,103,111, 97,108, 0,100,101,102,103,111, 97,108, 0,118,101,114,116,103, +114,111,117,112, 0,110, 97,109,101,100, 86, 71, 95, 83,111,102,116,103,111, 97,108, 91, 54, 52, 93, 0,102,117,122,122,121,110, +101,115,115, 0,105,110,115,112,114,105,110,103, 0,105,110,102,114,105, 99,116, 0,110, 97,109,101,100, 86, 71, 95, 83,112,114, +105,110,103, 95, 75, 91, 54, 52, 93, 0,101,102,114, 97, 0,105,110,116,101,114,118, 97,108, 0,108,111, 99, 97,108, 0,115,111, +108,118,101,114,102,108, 97,103,115, 0, 42, 42,107,101,121,115, 0,116,111,116,112,111,105,110,116,107,101,121, 0,115,101, 99, +111,110,100,115,112,114,105,110,103, 0, 99,111,108, 98, 97,108,108, 0, 98, 97,108,108,100, 97,109,112, 0, 98, 97,108,108,115, +116,105,102,102, 0,115, 98, 99, 95,109,111,100,101, 0, 97,101,114,111,101,100,103,101, 0,109,105,110,108,111,111,112,115, 0, +109, 97,120,108,111,111,112,115, 0, 99,104,111,107,101, 0,115,111,108,118,101,114, 95, 73, 68, 0,112,108, 97,115,116,105, 99, + 0,115,112,114,105,110,103,112,114,101,108,111, 97,100, 0, 42,115, 99,114, 97,116, 99,104, 0,115,104,101, 97,114,115,116,105, +102,102, 0,105,110,112,117,115,104, 0, 42,112,111,105,110,116, 99, 97, 99,104,101, 0, 42,101,102,102,101, 99,116,111,114, 95, +119,101,105,103,104,116,115, 0,108, 99,111,109, 91, 51, 93, 0,108,114,111,116, 91, 51, 93, 91, 51, 93, 0,108,115, 99, 97,108, +101, 91, 51, 93, 91, 51, 93, 0,108, 97,115,116, 95,102,114, 97,109,101, 0,118,101,108, 91, 51, 93, 0, 42,102,109,100, 0,115, +104,111,119, 95, 97,100,118, 97,110, 99,101,100,111,112,116,105,111,110,115, 0,114,101,115,111,108,117,116,105,111,110,120,121, +122, 0,112,114,101,118,105,101,119,114,101,115,120,121,122, 0,114,101, 97,108,115,105,122,101, 0,103,117,105, 68,105,115,112, +108, 97,121, 77,111,100,101, 0,114,101,110,100,101,114, 68,105,115,112,108, 97,121, 77,111,100,101, 0,118,105,115, 99,111,115, +105,116,121, 86, 97,108,117,101, 0,118,105,115, 99,111,115,105,116,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, + 69,120,112,111,110,101,110,116, 0,103,114, 97,118, 91, 51, 93, 0, 97,110,105,109, 83,116, 97,114,116, 0, 97,110,105,109, 69, +110,100, 0, 98, 97,107,101, 83,116, 97,114,116, 0, 98, 97,107,101, 69,110,100, 0,102,114, 97,109,101, 79,102,102,115,101,116, + 0,103,115,116, 97,114, 0,109, 97,120, 82,101,102,105,110,101, 0,105,110,105, 86,101,108,120, 0,105,110,105, 86,101,108,121, + 0,105,110,105, 86,101,108,122, 0, 42,111,114,103, 77,101,115,104, 0, 42,109,101,115,104, 66, 66, 0,115,117,114,102,100, 97, +116, 97, 80, 97,116,104, 91, 49, 48, 50, 52, 93, 0, 98, 98, 83,116, 97,114,116, 91, 51, 93, 0, 98, 98, 83,105,122,101, 91, 51, + 93, 0,116,121,112,101, 70,108, 97,103,115, 0,100,111,109, 97,105,110, 78,111,118,101, 99,103,101,110, 0,118,111,108,117,109, +101, 73,110,105,116, 84,121,112,101, 0,112, 97,114,116, 83,108,105,112, 86, 97,108,117,101, 0,103,101,110,101,114, 97,116,101, + 84,114, 97, 99,101,114,115, 0,103,101,110,101,114, 97,116,101, 80, 97,114,116,105, 99,108,101,115, 0,115,117,114,102, 97, 99, +101, 83,109,111,111,116,104,105,110,103, 0,115,117,114,102, 97, 99,101, 83,117, 98,100,105,118,115, 0,112, 97,114,116,105, 99, +108,101, 73,110,102, 83,105,122,101, 0,112, 97,114,116,105, 99,108,101, 73,110,102, 65,108,112,104, 97, 0,102, 97,114, 70,105, +101,108,100, 83,105,122,101, 0, 42,109,101,115,104, 86,101,108,111, 99,105,116,105,101,115, 0, 99,112,115, 84,105,109,101, 83, +116, 97,114,116, 0, 99,112,115, 84,105,109,101, 69,110,100, 0, 99,112,115, 81,117, 97,108,105,116,121, 0, 97,116,116,114, 97, + 99,116,102,111,114, 99,101, 83,116,114,101,110,103,116,104, 0, 97,116,116,114, 97, 99,116,102,111,114, 99,101, 82, 97,100,105, +117,115, 0,118,101,108,111, 99,105,116,121,102,111,114, 99,101, 83,116,114,101,110,103,116,104, 0,118,101,108,111, 99,105,116, +121,102,111,114, 99,101, 82, 97,100,105,117,115, 0,108, 97,115,116,103,111,111,100,102,114, 97,109,101, 0, 97,110,105,109, 82, + 97,116,101, 0,109,105,115,116,121,112,101, 0,104,111,114,114, 0,104,111,114,103, 0,104,111,114, 98, 0,122,101,110,114, 0, +122,101,110,103, 0,122,101,110, 98, 0,102, 97,115,116, 99,111,108, 0,101,120,112,111,115,117,114,101, 0,101,120,112, 0,114, + 97,110,103,101, 0,108,105,110,102, 97, 99, 0,108,111,103,102, 97, 99, 0,103,114, 97,118,105,116,121, 0, 97, 99,116,105,118, +105,116,121, 66,111,120, 82, 97,100,105,117,115, 0,115,107,121,116,121,112,101, 0,111, 99, 99,108,117,115,105,111,110, 82,101, +115, 0,112,104,121,115,105, 99,115, 69,110,103,105,110,101, 0,116,105, 99,114, 97,116,101, 0,109, 97,120,108,111,103,105, 99, +115,116,101,112, 0,112,104,121,115,117, 98,115,116,101,112, 0,109, 97,120,112,104,121,115,116,101,112, 0,109,105,115,105, 0, +109,105,115,116,115,116, 97, 0,109,105,115,116,100,105,115,116, 0,109,105,115,116,104,105, 0,115,116, 97,114,114, 0,115,116, + 97,114,103, 0,115,116, 97,114, 98, 0,115,116, 97,114,107, 0,115,116, 97,114,115,105,122,101, 0,115,116, 97,114,109,105,110, +100,105,115,116, 0,115,116, 97,114,100,105,115,116, 0,115,116, 97,114, 99,111,108,110,111,105,115,101, 0,100,111,102,115,116, + 97, 0,100,111,102,101,110,100, 0,100,111,102,109,105,110, 0,100,111,102,109, 97,120, 0, 97,111,100,105,115,116, 0, 97,111, +100,105,115,116,102, 97, 99, 0, 97,111,101,110,101,114,103,121, 0, 97,111, 98,105, 97,115, 0, 97,111,109,111,100,101, 0, 97, +111,115, 97,109,112, 0, 97,111,109,105,120, 0, 97,111, 99,111,108,111,114, 0, 97,111, 95, 97,100, 97,112,116, 95,116,104,114, +101,115,104, 0, 97,111, 95, 97,100, 97,112,116, 95,115,112,101,101,100, 95,102, 97, 99, 0, 97,111, 95, 97,112,112,114,111,120, + 95,101,114,114,111,114, 0, 97,111, 95, 97,112,112,114,111,120, 95, 99,111,114,114,101, 99,116,105,111,110, 0, 97,111, 95,105, +110,100,105,114,101, 99,116, 95,101,110,101,114,103,121, 0, 97,111, 95,101,110,118, 95,101,110,101,114,103,121, 0, 97,111, 95, +112, 97,100, 50, 0, 97,111, 95,105,110,100,105,114,101, 99,116, 95, 98,111,117,110, 99,101,115, 0, 97,111, 95,112, 97,100, 0, + 97,111, 95,115, 97,109,112, 95,109,101,116,104,111,100, 0, 97,111, 95,103, 97,116,104,101,114, 95,109,101,116,104,111,100, 0, + 97,111, 95, 97,112,112,114,111,120, 95,112, 97,115,115,101,115, 0, 42, 97,111,115,112,104,101,114,101, 0, 42, 97,111,116, 97, + 98,108,101,115, 0,115,101,108, 99,111,108, 0,115,120, 0,115,121, 0, 42,108,112, 70,111,114,109, 97,116, 0, 42,108,112, 80, + 97,114,109,115, 0, 99, 98, 70,111,114,109, 97,116, 0, 99, 98, 80, 97,114,109,115, 0,102, 99, 99, 84,121,112,101, 0,102, 99, + 99, 72, 97,110,100,108,101,114, 0,100,119, 75,101,121, 70,114, 97,109,101, 69,118,101,114,121, 0,100,119, 81,117, 97,108,105, +116,121, 0,100,119, 66,121,116,101,115, 80,101,114, 83,101, 99,111,110,100, 0,100,119, 70,108, 97,103,115, 0,100,119, 73,110, +116,101,114,108,101, 97,118,101, 69,118,101,114,121, 0, 97,118,105, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, + 42, 99,100, 80, 97,114,109,115, 0, 42,112, 97,100, 0, 99,100, 83,105,122,101, 0,113,116, 99,111,100,101, 99,110, 97,109,101, + 91, 49, 50, 56, 93, 0, 99,111,100,101, 99, 84,121,112,101, 0, 99,111,100,101, 99, 83,112, 97,116,105, 97,108, 81,117, 97,108, +105,116,121, 0, 99,111,100,101, 99, 0, 99,111,100,101, 99, 70,108, 97,103,115, 0, 99,111,108,111,114, 68,101,112,116,104, 0, + 99,111,100,101, 99, 84,101,109,112,111,114, 97,108, 81,117, 97,108,105,116,121, 0,109,105,110, 83,112, 97,116,105, 97,108, 81, +117, 97,108,105,116,121, 0,109,105,110, 84,101,109,112,111,114, 97,108, 81,117, 97,108,105,116,121, 0,107,101,121, 70,114, 97, +109,101, 82, 97,116,101, 0, 98,105,116, 82, 97,116,101, 0, 97,117,100,105,111, 99,111,100,101, 99, 84,121,112,101, 0, 97,117, +100,105,111, 83, 97,109,112,108,101, 82, 97,116,101, 0, 97,117,100,105,111, 66,105,116, 68,101,112,116,104, 0, 97,117,100,105, +111, 67,104, 97,110,110,101,108,115, 0, 97,117,100,105,111, 67,111,100,101, 99, 70,108, 97,103,115, 0, 97,117,100,105,111, 66, +105,116, 82, 97,116,101, 0, 97,117,100,105,111, 95, 99,111,100,101, 99, 0,118,105,100,101,111, 95, 98,105,116,114, 97,116,101, + 0, 97,117,100,105,111, 95, 98,105,116,114, 97,116,101, 0, 97,117,100,105,111, 95,109,105,120,114, 97,116,101, 0, 97,117,100, +105,111, 95, 99,104, 97,110,110,101,108,115, 0, 97,117,100,105,111, 95,112, 97,100, 0, 97,117,100,105,111, 95,118,111,108,117, +109,101, 0,103,111,112, 95,115,105,122,101, 0,114, 99, 95,109,105,110, 95,114, 97,116,101, 0,114, 99, 95,109, 97,120, 95,114, + 97,116,101, 0,114, 99, 95, 98,117,102,102,101,114, 95,115,105,122,101, 0,109,117,120, 95,112, 97, 99,107,101,116, 95,115,105, +122,101, 0,109,117,120, 95,114, 97,116,101, 0,109,105,120,114, 97,116,101, 0,109, 97,105,110, 0,115,112,101,101,100, 95,111, +102, 95,115,111,117,110,100, 0,100,111,112,112,108,101,114, 95,102, 97, 99,116,111,114, 0,100,105,115,116, 97,110, 99,101, 95, +109,111,100,101,108, 0, 42,109, 97,116, 95,111,118,101,114,114,105,100,101, 0, 42,108,105,103,104,116, 95,111,118,101,114,114, +105,100,101, 0,108, 97,121, 95,122,109, 97,115,107, 0,108, 97,121,102,108, 97,103, 0,112, 97,115,115,102,108, 97,103, 0,112, + 97,115,115, 95,120,111,114, 0,105,109,116,121,112,101, 0,112,108, 97,110,101,115, 0,113,117, 97,108,105,116,121, 0, 99,111, +109,112,114,101,115,115, 0,101,120,114, 95, 99,111,100,101, 99, 0, 99,105,110,101,111,110, 95,102,108, 97,103, 0, 99,105,110, +101,111,110, 95,119,104,105,116,101, 0, 99,105,110,101,111,110, 95, 98,108, 97, 99,107, 0, 99,105,110,101,111,110, 95,103, 97, +109,109, 97, 0,106,112, 50, 95,102,108, 97,103, 0,105,109, 95,102,111,114,109, 97,116, 0, 42, 97,118,105, 99,111,100,101, 99, +100, 97,116, 97, 0, 42,113,116, 99,111,100,101, 99,100, 97,116, 97, 0,113,116, 99,111,100,101, 99,115,101,116,116,105,110,103, +115, 0,102,102, 99,111,100,101, 99,100, 97,116, 97, 0,115,117, 98,102,114, 97,109,101, 0,112,115,102,114, 97, 0,112,101,102, +114, 97, 0,105,109, 97,103,101,115, 0,102,114, 97,109, 97,112,116,111, 0,116,104,114,101, 97,100,115, 0,102,114, 97,109,101, +108,101,110, 0, 98,108,117,114,102, 97, 99, 0,101,100,103,101, 82, 0,101,100,103,101, 71, 0,101,100,103,101, 66, 0,102,117, +108,108,115, 99,114,101,101,110, 0,120,112,108, 97,121, 0,121,112,108, 97,121, 0,102,114,101,113,112,108, 97,121, 0, 97,116, +116,114,105, 98, 0,102,114, 97,109,101, 95,115,116,101,112, 0,115,116,101,114,101,111,109,111,100,101, 0,100,105,109,101,110, +115,105,111,110,115,112,114,101,115,101,116, 0,109, 97,120,105,109,115,105,122,101, 0,120,115, 99,104, 0,121,115, 99,104, 0, +120,112, 97,114,116,115, 0,121,112, 97,114,116,115, 0,115,117, 98,105,109,116,121,112,101, 0,100,105,115,112,108, 97,121,109, +111,100,101, 0,115, 99,101,109,111,100,101, 0,114, 97,121,116,114, 97, 99,101, 95,111,112,116,105,111,110,115, 0,114, 97,121, +116,114, 97, 99,101, 95,115,116,114,117, 99,116,117,114,101, 0,111, 99,114,101,115, 0,112, 97,100, 52, 0, 97,108,112,104, 97, +109,111,100,101, 0,111,115, 97, 0,102,114,115, 95,115,101, 99, 0,101,100,103,101,105,110,116, 0,115, 97,102,101,116,121, 0, + 98,111,114,100,101,114, 0,100,105,115,112,114,101, 99,116, 0,108, 97,121,101,114,115, 0, 97, 99,116,108, 97,121, 0,109, 98, +108,117,114, 95,115, 97,109,112,108,101,115, 0,120, 97,115,112, 0,121, 97,115,112, 0,102,114,115, 95,115,101, 99, 95, 98, 97, +115,101, 0,103, 97,117,115,115, 0, 99,111,108,111,114, 95,109,103,116, 95,102,108, 97,103, 0,112,111,115,116,103, 97,109,109, + 97, 0,112,111,115,116,104,117,101, 0,112,111,115,116,115, 97,116, 0,100,105,116,104,101,114, 95,105,110,116,101,110,115,105, +116,121, 0, 98, 97,107,101, 95,111,115, 97, 0, 98, 97,107,101, 95,102,105,108,116,101,114, 0, 98, 97,107,101, 95,109,111,100, +101, 0, 98, 97,107,101, 95,102,108, 97,103, 0, 98, 97,107,101, 95,110,111,114,109, 97,108, 95,115,112, 97, 99,101, 0, 98, 97, +107,101, 95,113,117, 97,100, 95,115,112,108,105,116, 0, 98, 97,107,101, 95,109, 97,120,100,105,115,116, 0, 98, 97,107,101, 95, + 98,105, 97,115,100,105,115,116, 0, 98, 97,107,101, 95,112, 97,100, 0,112,105, 99, 91, 49, 48, 50, 52, 93, 0,115,116, 97,109, +112, 0,115,116, 97,109,112, 95,102,111,110,116, 95,105,100, 0,115,116, 97,109,112, 95,117,100, 97,116, 97, 91, 55, 54, 56, 93, + 0,102,103, 95,115,116, 97,109,112, 91, 52, 93, 0, 98,103, 95,115,116, 97,109,112, 91, 52, 93, 0,115,101,113, 95,112,114,101, +118, 95,116,121,112,101, 0,115,101,113, 95,114,101,110,100, 95,116,121,112,101, 0,115,101,113, 95,102,108, 97,103, 0,112, 97, +100, 53, 91, 53, 93, 0,115,105,109,112,108,105,102,121, 95,102,108, 97,103, 0,115,105,109,112,108,105,102,121, 95,115,117, 98, +115,117,114,102, 0,115,105,109,112,108,105,102,121, 95,115,104, 97,100,111,119,115, 97,109,112,108,101,115, 0,115,105,109,112, +108,105,102,121, 95,112, 97,114,116,105, 99,108,101,115, 0,115,105,109,112,108,105,102,121, 95, 97,111,115,115,115, 0, 99,105, +110,101,111,110,119,104,105,116,101, 0, 99,105,110,101,111,110, 98,108, 97, 99,107, 0, 99,105,110,101,111,110,103, 97,109,109, + 97, 0,106,112, 50, 95,112,114,101,115,101,116, 0,106,112, 50, 95,100,101,112,116,104, 0,114,112, 97,100, 51, 0,100,111,109, +101,114,101,115, 0,100,111,109,101,109,111,100,101, 0,100,111,109,101, 97,110,103,108,101, 0,100,111,109,101,116,105,108,116, + 0,100,111,109,101,114,101,115, 98,117,102, 0, 42,100,111,109,101,116,101,120,116, 0,101,110,103,105,110,101, 91, 51, 50, 93, + 0,110, 97,109,101, 91, 51, 50, 93, 0,112, 97,114,116,105, 99,108,101, 95,112,101,114, 99, 0,115,117, 98,115,117,114,102, 95, +109, 97,120, 0,115,104, 97,100, 98,117,102,115, 97,109,112,108,101, 95,109, 97,120, 0, 97,111, 95,101,114,114,111,114, 0,116, +105,108,116, 0,114,101,115, 98,117,102, 0, 42,119, 97,114,112,116,101,120,116, 0, 99,111,108, 91, 51, 93, 0, 99,101,108,108, +115,105,122,101, 0, 99,101,108,108,104,101,105,103,104,116, 0, 97,103,101,110,116,109, 97,120,115,108,111,112,101, 0, 97,103, +101,110,116,109, 97,120, 99,108,105,109, 98, 0, 97,103,101,110,116,104,101,105,103,104,116, 0, 97,103,101,110,116,114, 97,100, +105,117,115, 0,101,100,103,101,109, 97,120,108,101,110, 0,101,100,103,101,109, 97,120,101,114,114,111,114, 0,114,101,103,105, +111,110,109,105,110,115,105,122,101, 0,114,101,103,105,111,110,109,101,114,103,101,115,105,122,101, 0,118,101,114,116,115,112, +101,114,112,111,108,121, 0,100,101,116, 97,105,108,115, 97,109,112,108,101,100,105,115,116, 0,100,101,116, 97,105,108,115, 97, +109,112,108,101,109, 97,120,101,114,114,111,114, 0,102,114, 97,109,105,110,103, 0,112,108, 97,121,101,114,102,108, 97,103, 0, +114,116, 49, 0,114,116, 50, 0, 97, 97,115, 97,109,112,108,101,115, 0,112, 97,100, 52, 91, 51, 93, 0,100,111,109,101, 0,115, +116,101,114,101,111,102,108, 97,103, 0,101,121,101,115,101,112, 97,114, 97,116,105,111,110, 0,114,101, 99, 97,115,116, 68, 97, +116, 97, 0,109, 97,116,109,111,100,101, 0,101,120,105,116,107,101,121, 0,111, 98,115,116, 97, 99,108,101, 83,105,109,117,108, + 97,116,105,111,110, 0,108,101,118,101,108, 72,101,105,103,104,116, 0, 42, 99, 97,109,101,114, 97, 0, 42,112, 97,105,110,116, + 95, 99,117,114,115,111,114, 0,112, 97,105,110,116, 95, 99,117,114,115,111,114, 95, 99,111,108, 91, 52, 93, 0,112, 97,105,110, +116, 0,115,101, 97,109, 95, 98,108,101,101,100, 0,110,111,114,109, 97,108, 95, 97,110,103,108,101, 0,115, 99,114,101,101,110, + 95,103,114, 97, 98, 95,115,105,122,101, 91, 50, 93, 0, 42,112, 97,105,110,116, 99,117,114,115,111,114, 0,105,110,118,101,114, +116, 0,116,111,116,114,101,107,101,121, 0,116,111,116, 97,100,100,107,101,121, 0, 98,114,117,115,104,116,121,112,101, 0, 98, +114,117,115,104, 91, 55, 93, 0,101,109,105,116,116,101,114,100,105,115,116, 0,115,101,108,101, 99,116,109,111,100,101, 0,101, +100,105,116,116,121,112,101, 0,100,114, 97,119, 95,115,116,101,112, 0,102, 97,100,101, 95,102,114, 97,109,101,115, 0,114, 97, +100,105, 97,108, 95,115,121,109,109, 91, 51, 93, 0,108, 97,115,116, 95,120, 0,108, 97,115,116, 95,121, 0,108, 97,115,116, 95, + 97,110,103,108,101, 0,100,114, 97,119, 95, 97,110, 99,104,111,114,101,100, 0, 97,110, 99,104,111,114,101,100, 95,115,105,122, +101, 0, 97,110, 99,104,111,114,101,100, 95,108,111, 99, 97,116,105,111,110, 91, 51, 93, 0, 97,110, 99,104,111,114,101,100, 95, +105,110,105,116,105, 97,108, 95,109,111,117,115,101, 91, 50, 93, 0,100,114, 97,119, 95,112,114,101,115,115,117,114,101, 0,112, +114,101,115,115,117,114,101, 95,118, 97,108,117,101, 0,115,112,101, 99,105, 97,108, 95,114,111,116, 97,116,105,111,110, 0, 42, +118,112, 97,105,110,116, 95,112,114,101,118, 0, 42,119,112, 97,105,110,116, 95,112,114,101,118, 0,109, 97,116, 91, 51, 93, 91, + 51, 93, 0,117,110,112,114,111,106,101, 99,116,101,100, 95,114, 97,100,105,117,115, 0, 42,118,112, 97,105,110,116, 0, 42,119, +112, 97,105,110,116, 0, 42,117,118,115, 99,117,108,112,116, 0,118,103,114,111,117,112, 95,119,101,105,103,104,116, 0, 99,111, +114,110,101,114,116,121,112,101, 0,101,100,105,116, 98,117,116,102,108, 97,103, 0,106,111,105,110,116,114,105,108,105,109,105, +116, 0,100,101,103,114, 0,116,117,114,110, 0,101,120,116,114, 95,111,102,102,115, 0,100,111,117, 98,108,105,109,105,116, 0, +110,111,114,109, 97,108,115,105,122,101, 0, 97,117,116,111,109,101,114,103,101, 0,115,101,103,109,101,110,116,115, 0,114,105, +110,103,115, 0,118,101,114,116,105, 99,101,115, 0,117,110,119,114, 97,112,112,101,114, 0,117,118, 99, 97,108, 99, 95,114, 97, +100,105,117,115, 0,117,118, 99, 97,108, 99, 95, 99,117, 98,101,115,105,122,101, 0,117,118, 99, 97,108, 99, 95,109, 97,114,103, +105,110, 0,117,118, 99, 97,108, 99, 95,109, 97,112,100,105,114, 0,117,118, 99, 97,108, 99, 95,109, 97,112, 97,108,105,103,110, + 0,117,118, 99, 97,108, 99, 95,102,108, 97,103, 0,117,118, 95,102,108, 97,103, 0,117,118, 95,115,101,108,101, 99,116,109,111, +100,101, 0,117,118, 95,115,117, 98,115,117,114,102, 95,108,101,118,101,108, 0,103,112,101,110, 99,105,108, 95,102,108, 97,103, +115, 0, 97,117,116,111,105,107, 95, 99,104, 97,105,110,108,101,110, 0,105,109, 97,112, 97,105,110,116, 0,112, 97,114,116,105, + 99,108,101, 0,112,114,111,112,111,114,116,105,111,110, 97,108, 95,115,105,122,101, 0,115,101,108,101, 99,116, 95,116,104,114, +101,115,104, 0, 99,108,101, 97,110, 95,116,104,114,101,115,104, 0, 97,117,116,111,107,101,121, 95,109,111,100,101, 0, 97,117, +116,111,107,101,121, 95,102,108, 97,103, 0,109,117,108,116,105,114,101,115, 95,115,117, 98,100,105,118, 95,116,121,112,101, 0, +112, 97,100, 50, 91, 53, 93, 0,115,107,103,101,110, 95,114,101,115,111,108,117,116,105,111,110, 0,115,107,103,101,110, 95,116, +104,114,101,115,104,111,108,100, 95,105,110,116,101,114,110, 97,108, 0,115,107,103,101,110, 95,116,104,114,101,115,104,111,108, +100, 95,101,120,116,101,114,110, 97,108, 0,115,107,103,101,110, 95,108,101,110,103,116,104, 95,114, 97,116,105,111, 0,115,107, +103,101,110, 95,108,101,110,103,116,104, 95,108,105,109,105,116, 0,115,107,103,101,110, 95, 97,110,103,108,101, 95,108,105,109, +105,116, 0,115,107,103,101,110, 95, 99,111,114,114,101,108, 97,116,105,111,110, 95,108,105,109,105,116, 0,115,107,103,101,110, + 95,115,121,109,109,101,116,114,121, 95,108,105,109,105,116, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95, 97, +110,103,108,101, 95,119,101,105,103,104,116, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,108,101,110,103,116, +104, 95,119,101,105,103,104,116, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,100,105,115,116, 97,110, 99,101, + 95,119,101,105,103,104,116, 0,115,107,103,101,110, 95,111,112,116,105,111,110,115, 0,115,107,103,101,110, 95,112,111,115,116, +112,114,111, 0,115,107,103,101,110, 95,112,111,115,116,112,114,111, 95,112, 97,115,115,101,115, 0,115,107,103,101,110, 95,115, +117, 98,100,105,118,105,115,105,111,110,115, 91, 51, 93, 0,115,107,103,101,110, 95,109,117,108,116,105, 95,108,101,118,101,108, + 0, 42,115,107,103,101,110, 95,116,101,109,112,108, 97,116,101, 0, 98,111,110,101, 95,115,107,101,116, 99,104,105,110,103, 0, + 98,111,110,101, 95,115,107,101,116, 99,104,105,110,103, 95, 99,111,110,118,101,114,116, 0,115,107,103,101,110, 95,115,117, 98, +100,105,118,105,115,105,111,110, 95,110,117,109, 98,101,114, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,111, +112,116,105,111,110,115, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,114,111,108,108, 0,115,107,103,101,110, + 95,115,105,100,101, 95,115,116,114,105,110,103, 91, 56, 93, 0,115,107,103,101,110, 95,110,117,109, 95,115,116,114,105,110,103, + 91, 56, 93, 0,101,100,103,101, 95,109,111,100,101, 0,101,100,103,101, 95,109,111,100,101, 95,108,105,118,101, 95,117,110,119, +114, 97,112, 0,115,110, 97,112, 95,109,111,100,101, 0,115,110, 97,112, 95,102,108, 97,103, 0,115,110, 97,112, 95,116, 97,114, +103,101,116, 0,112,114,111,112,111,114,116,105,111,110, 97,108, 0,112,114,111,112, 95,109,111,100,101, 0,112,114,111,112,111, +114,116,105,111,110, 97,108, 95,111, 98,106,101, 99,116,115, 0,112, 97,100, 91, 53, 93, 0, 97,117,116,111, 95,110,111,114,109, + 97,108,105,122,101, 0,109,117,108,116,105,112, 97,105,110,116, 0,117,115,101, 95,117,118, 95,115, 99,117,108,112,116, 0,117, +118, 95,115, 99,117,108,112,116, 95,115,101,116,116,105,110,103,115, 0,117,118, 95,115, 99,117,108,112,116, 95,116,111,111,108, + 0,117,118, 95,114,101,108, 97,120, 95,109,101,116,104,111,100, 0,115, 99,117,108,112,116, 95,112, 97,105,110,116, 95,115,101, +116,116,105,110,103,115, 0,115, 99,117,108,112,116, 95,112, 97,105,110,116, 95,117,110,105,102,105,101,100, 95,115,105,122,101, + 0,115, 99,117,108,112,116, 95,112, 97,105,110,116, 95,117,110,105,102,105,101,100, 95,117,110,112,114,111,106,101, 99,116,101, +100, 95,114, 97,100,105,117,115, 0,115, 99,117,108,112,116, 95,112, 97,105,110,116, 95,117,110,105,102,105,101,100, 95, 97,108, +112,104, 97, 0,117,110,105,102,105,101,100, 95,112, 97,105,110,116, 95,115,101,116,116,105,110,103,115, 0,116,111,116,111, 98, +106, 0,116,111,116,108, 97,109,112, 0,116,111,116,111, 98,106,115,101,108, 0,116,111,116, 99,117,114,118,101, 0,116,111,116, +109,101,115,104, 0,116,111,116, 97,114,109, 97,116,117,114,101, 0,115, 99, 97,108,101, 95,108,101,110,103,116,104, 0,115,121, +115,116,101,109, 0,115,121,115,116,101,109, 95,114,111,116, 97,116,105,111,110, 0,103,114, 97,118,105,116,121, 91, 51, 93, 0, +113,117,105, 99,107, 95, 99, 97, 99,104,101, 95,115,116,101,112, 0, 42,119,111,114,108,100, 0, 42,115,101,116, 0, 98, 97,115, +101, 0, 42, 98, 97,115, 97, 99,116, 0, 42,111, 98,101,100,105,116, 0, 99,117,114,115,111,114, 91, 51, 93, 0,116,119, 99,101, +110,116, 91, 51, 93, 0,116,119,109,105,110, 91, 51, 93, 0,116,119,109, 97,120, 91, 51, 93, 0,108, 97,121, 97, 99,116, 0,108, + 97,121, 95,117,112,100, 97,116,101,100, 0, 42,101,100, 0, 42,116,111,111,108,115,101,116,116,105,110,103,115, 0, 42,115,116, + 97,116,115, 0, 97,117,100,105,111, 0,116,114, 97,110,115,102,111,114,109, 95,115,112, 97, 99,101,115, 0, 42,115,111,117,110, +100, 95,115, 99,101,110,101, 0, 42,115,111,117,110,100, 95,115, 99,101,110,101, 95,104, 97,110,100,108,101, 0, 42,115,111,117, +110,100, 95,115, 99,114,117, 98, 95,104, 97,110,100,108,101, 0, 42,115,112,101, 97,107,101,114, 95,104, 97,110,100,108,101,115, + 0, 42,102,112,115, 95,105,110,102,111, 0, 42,116,104,101, 68, 97,103, 0,100, 97,103,105,115,118, 97,108,105,100, 0,100, 97, +103,102,108, 97,103,115, 0, 97, 99,116,105,118,101, 95,107,101,121,105,110,103,115,101,116, 0,107,101,121,105,110,103,115,101, +116,115, 0,103,109, 0,117,110,105,116, 0,112,104,121,115,105, 99,115, 95,115,101,116,116,105,110,103,115, 0, 42, 99,108,105, +112, 0, 99,117,115,116,111,109,100, 97,116, 97, 95,109, 97,115,107, 95,109,111,100, 97,108, 0, 99,117,115,101,114, 0, 98,108, +101,110,100, 0,118,105,101,119, 0,119,105,110,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,109, 97,116, 91, 52, 93, + 91, 52, 93, 0,118,105,101,119,105,110,118, 91, 52, 93, 91, 52, 93, 0,112,101,114,115,109, 97,116, 91, 52, 93, 91, 52, 93, 0, +112,101,114,115,105,110,118, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,109, 97,116,111, 98, 91, 52, 93, 91, 52, 93, 0,112,101, +114,115,109, 97,116,111, 98, 91, 52, 93, 91, 52, 93, 0, 99,108,105,112, 91, 54, 93, 91, 52, 93, 0, 99,108,105,112, 95,108,111, + 99, 97,108, 91, 54, 93, 91, 52, 93, 0, 42, 99,108,105,112, 98, 98, 0, 42,108,111, 99, 97,108,118,100, 0, 42,114,105, 0, 42, +114,101,110,100,101,114, 95,101,110,103,105,110,101, 0, 42,100,101,112,116,104,115, 0, 42,115,109,115, 0, 42,115,109,111,111, +116,104, 95,116,105,109,101,114, 0,116,119,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,113,117, 97,116, 91, 52, 93, + 0,122,102, 97, 99, 0, 99, 97,109,100,120, 0, 99, 97,109,100,121, 0,112,105,120,115,105,122,101, 0, 99, 97,109,122,111,111, +109, 0,105,115, 95,112,101,114,115,112, 0,112,101,114,115,112, 0,118,105,101,119,108,111, 99,107, 0,116,119,100,114, 97,119, +102,108, 97,103, 0,114,102,108, 97,103, 0,108,118,105,101,119,113,117, 97,116, 91, 52, 93, 0,108,112,101,114,115,112, 0,108, +118,105,101,119, 0,103,114,105,100,118,105,101,119, 0,116,119, 97,110,103,108,101, 91, 51, 93, 0,114,111,116, 95, 97,110,103, +108,101, 0,114,111,116, 95, 97,120,105,115, 91, 51, 93, 0,114,101,103,105,111,110, 98, 97,115,101, 0,115,112, 97, 99,101,116, +121,112,101, 0, 98,108,111, 99,107,115, 99, 97,108,101, 0, 98,108,111, 99,107,104, 97,110,100,108,101,114, 91, 56, 93, 0, 98, +117,110,100,108,101, 95,115,105,122,101, 0, 98,117,110,100,108,101, 95,100,114, 97,119,116,121,112,101, 0,108, 97,121, 95,117, +115,101,100, 0, 42,111, 98, 95, 99,101,110,116,114,101, 0, 98,103,112,105, 99, 98, 97,115,101, 0, 42, 98,103,112,105, 99, 0, +111, 98, 95, 99,101,110,116,114,101, 95, 98,111,110,101, 91, 54, 52, 93, 0,100,114, 97,119,116,121,112,101, 0,111, 98, 95, 99, +101,110,116,114,101, 95, 99,117,114,115,111,114, 0,115, 99,101,110,101,108,111, 99,107, 0, 97,114,111,117,110,100, 0,103,114, +105,100, 0,110,101, 97,114, 0,102, 97,114, 0,109,111,100,101,115,101,108,101, 99,116, 0,103,114,105,100,108,105,110,101,115, + 0,103,114,105,100,115,117, 98,100,105,118, 0,103,114,105,100,102,108, 97,103, 0,116,119,116,121,112,101, 0,116,119,109,111, +100,101, 0,116,119,102,108, 97,103, 0,112, 97,100, 50, 91, 50, 93, 0, 97,102,116,101,114,100,114, 97,119, 95,116,114, 97,110, +115,112, 0, 97,102,116,101,114,100,114, 97,119, 95,120,114, 97,121, 0, 97,102,116,101,114,100,114, 97,119, 95,120,114, 97,121, +116,114, 97,110,115,112, 0,122, 98,117,102, 0,120,114, 97,121, 0,112, 97,100, 51, 91, 50, 93, 0, 42,112,114,111,112,101,114, +116,105,101,115, 95,115,116,111,114, 97,103,101, 0,118,101,114,116, 0,104,111,114, 0,109, 97,115,107, 0,109,105,110, 91, 50, + 93, 0,109, 97,120, 91, 50, 93, 0,109,105,110,122,111,111,109, 0,109, 97,120,122,111,111,109, 0,115, 99,114,111,108,108, 0, +115, 99,114,111,108,108, 95,117,105, 0,107,101,101,112,116,111,116, 0,107,101,101,112,122,111,111,109, 0,107,101,101,112,111, +102,115, 0, 97,108,105,103,110, 0,119,105,110,120, 0,119,105,110,121, 0,111,108,100,119,105,110,120, 0,111,108,100,119,105, +110,121, 0, 42,116, 97, 98, 95,111,102,102,115,101,116, 0,116, 97, 98, 95,110,117,109, 0,116, 97, 98, 95, 99,117,114, 0,114, +112,116, 95,109, 97,115,107, 0,118, 50,100, 0, 42, 97,100,115, 0,103,104,111,115,116, 67,117,114,118,101,115, 0, 97,117,116, +111,115,110, 97,112, 0, 99,117,114,115,111,114, 86, 97,108, 0,109, 97,105,110, 98, 0,109, 97,105,110, 98,111, 0,109, 97,105, +110, 98,117,115,101,114, 0,114,101, 95, 97,108,105,103,110, 0,112,114,101,118,105,101,119, 0,116,101,120,116,117,114,101, 95, + 99,111,110,116,101,120,116, 0,112, 97,116,104,102,108, 97,103, 0,100, 97,116, 97,105, 99,111,110, 0, 42,112,105,110,105,100, + 0, 42,116,101,120,117,115,101,114, 0,114,101,110,100,101,114, 95,115,105,122,101, 0, 99,104, 97,110,115,104,111,119,110, 0, +122,101, 98,114, 97, 0,122,111,111,109, 0,116,105,116,108,101, 91, 51, 50, 93, 0,100,105,114, 91, 49, 48, 53, 54, 93, 0,102, +105,108,101, 91, 50, 53, 54, 93, 0,114,101,110, 97,109,101,102,105,108,101, 91, 50, 53, 54, 93, 0,114,101,110, 97,109,101,101, +100,105,116, 91, 50, 53, 54, 93, 0,102,105,108,116,101,114, 95,103,108,111, 98, 91, 54, 52, 93, 0, 97, 99,116,105,118,101, 95, +102,105,108,101, 0,115,101,108, 95,102,105,114,115,116, 0,115,101,108, 95,108, 97,115,116, 0,115,111,114,116, 0,100,105,115, +112,108, 97,121, 0,102, 95,102,112, 0,102,112, 95,115,116,114, 91, 56, 93, 0,115, 99,114,111,108,108, 95,111,102,102,115,101, +116, 0, 42,112, 97,114, 97,109,115, 0, 42,102,105,108,101,115, 0, 42,102,111,108,100,101,114,115, 95,112,114,101,118, 0, 42, +102,111,108,100,101,114,115, 95,110,101,120,116, 0, 42,111,112, 0, 42,115,109,111,111,116,104,115, 99,114,111,108,108, 95,116, +105,109,101,114, 0, 42,108, 97,121,111,117,116, 0,114,101, 99,101,110,116,110,114, 0, 98,111,111,107,109, 97,114,107,110,114, + 0,115,121,115,116,101,109,110,114, 0,116,114,101,101, 0, 42,116,114,101,101,115,116,111,114,101, 0,115,101, 97,114, 99,104, + 95,115,116,114,105,110,103, 91, 51, 50, 93, 0,115,101, 97,114, 99,104, 95,116,115,101, 0,111,117,116,108,105,110,101,118,105, +115, 0,115,116,111,114,101,102,108, 97,103, 0,115,101, 97,114, 99,104, 95,102,108, 97,103,115, 0, 42, 99,117,109, 97,112, 0, +115, 99,111,112,101,115, 0,115, 97,109,112,108,101, 95,108,105,110,101, 95,104,105,115,116, 0, 99,117,114,115,111,114, 91, 50, + 93, 0, 99,101,110,116,120, 0, 99,101,110,116,121, 0, 99,117,114,116,105,108,101, 0,108,111, 99,107, 0,112,105,110, 0,100, +116, 95,117,118, 0,115,116,105, 99,107,121, 0,100,116, 95,117,118,115,116,114,101,116, 99,104, 0, 42,116,101,120,116, 0,116, +111,112, 0,118,105,101,119,108,105,110,101,115, 0,109,101,110,117,110,114, 0,108,104,101,105,103,104,116, 0, 99,119,105,100, +116,104, 0,108,105,110,101,110,114,115, 95,116,111,116, 0,108,101,102,116, 0,115,104,111,119,108,105,110,101,110,114,115, 0, +116, 97, 98,110,117,109, 98,101,114, 0,115,104,111,119,115,121,110,116, 97,120, 0,108,105,110,101, 95,104,108,105,103,104,116, + 0,111,118,101,114,119,114,105,116,101, 0,108,105,118,101, 95,101,100,105,116, 0,112,105,120, 95,112,101,114, 95,108,105,110, +101, 0,116,120,116,115, 99,114,111,108,108, 0,116,120,116, 98, 97,114, 0,119,111,114,100,119,114, 97,112, 0,100,111,112,108, +117,103,105,110,115, 0,102,105,110,100,115,116,114, 91, 50, 53, 54, 93, 0,114,101,112,108, 97, 99,101,115,116,114, 91, 50, 53, + 54, 93, 0,109, 97,114,103,105,110, 95, 99,111,108,117,109,110, 0, 42,100,114, 97,119, 99, 97, 99,104,101, 0, 42,112,121, 95, +100,114, 97,119, 0, 42,112,121, 95,101,118,101,110,116, 0, 42,112,121, 95, 98,117,116,116,111,110, 0, 42,112,121, 95, 98,114, +111,119,115,101,114, 99, 97,108,108, 98, 97, 99,107, 0, 42,112,121, 95,103,108,111, 98, 97,108,100,105, 99,116, 0,108, 97,115, +116,115,112, 97, 99,101, 0,115, 99,114,105,112,116,110, 97,109,101, 91, 49, 48, 50, 52, 93, 0,115, 99,114,105,112,116, 97,114, +103, 91, 50, 53, 54, 93, 0, 42,115, 99,114,105,112,116, 0, 42, 98,117,116, 95,114,101,102,115, 0, 42, 97,114,114, 97,121, 0, + 99, 97, 99,104,101,115, 0, 99, 97, 99,104,101, 95,100,105,115,112,108, 97,121, 0, 42,105,100, 0, 97,115,112,101, 99,116, 0, +112, 97,100,102, 0,109,120, 0,109,121, 0, 42,101,100,105,116,116,114,101,101, 0,116,114,101,101,116,121,112,101, 0,116,101, +120,102,114,111,109, 0,115,104, 97,100,101,114,102,114,111,109, 0,108,105,110,107,100,114, 97,103, 0,108,101,110, 95, 97,108, +108,111, 99, 0, 99,117,114,115,111,114, 0,115, 99,114,111,108,108, 98, 97, 99,107, 0,104,105,115,116,111,114,121, 0,112,114, +111,109,112,116, 91, 50, 53, 54, 93, 0,108, 97,110,103,117, 97,103,101, 91, 51, 50, 93, 0,115,101,108, 95,115,116, 97,114,116, + 0,115,101,108, 95,101,110,100, 0,102,105,108,116,101,114, 91, 54, 52, 93, 0,120,108,111, 99,107,111,102, 0,121,108,111, 99, +107,111,102, 0,117,115,101,114, 0,112, 97,116,104, 95,108,101,110,103,116,104, 0,108,111, 99, 91, 50, 93, 0,115,116, 97, 98, +109, 97,116, 91, 52, 93, 91, 52, 93, 0,117,110,105,115,116, 97, 98,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,116,112, +114,111, 99, 95,102,108, 97,103, 0, 42,100,114, 97,119, 95, 99,111,110,116,101,120,116, 0,102,105,108,101,110, 97,109,101, 91, + 49, 48, 50, 52, 93, 0, 98,108,102, 95,105,100, 0,117,105,102,111,110,116, 95,105,100, 0,114, 95,116,111, 95,108, 0,112,111, +105,110,116,115, 0,107,101,114,110,105,110,103, 0,105,116, 97,108,105, 99, 0, 98,111,108,100, 0,115,104, 97,100,111,119, 0, +115,104, 97,100,120, 0,115,104, 97,100,121, 0,115,104, 97,100,111,119, 97,108,112,104, 97, 0,115,104, 97,100,111,119, 99,111, +108,111,114, 0,112, 97,110,101,108,116,105,116,108,101, 0,103,114,111,117,112,108, 97, 98,101,108, 0,119,105,100,103,101,116, +108, 97, 98,101,108, 0,119,105,100,103,101,116, 0,112, 97,110,101,108,122,111,111,109, 0,109,105,110,108, 97, 98,101,108, 99, +104, 97,114,115, 0,109,105,110,119,105,100,103,101,116, 99,104, 97,114,115, 0, 99,111,108,117,109,110,115,112, 97, 99,101, 0, +116,101,109,112,108, 97,116,101,115,112, 97, 99,101, 0, 98,111,120,115,112, 97, 99,101, 0, 98,117,116,116,111,110,115,112, 97, + 99,101,120, 0, 98,117,116,116,111,110,115,112, 97, 99,101,121, 0,112, 97,110,101,108,115,112, 97, 99,101, 0,112, 97,110,101, +108,111,117,116,101,114, 0,111,117,116,108,105,110,101, 91, 52, 93, 0,105,110,110,101,114, 91, 52, 93, 0,105,110,110,101,114, + 95,115,101,108, 91, 52, 93, 0,105,116,101,109, 91, 52, 93, 0,116,101,120,116, 91, 52, 93, 0,116,101,120,116, 95,115,101,108, + 91, 52, 93, 0,115,104, 97,100,101,100, 0,115,104, 97,100,101,116,111,112, 0,115,104, 97,100,101,100,111,119,110, 0, 97,108, +112,104, 97, 95, 99,104,101, 99,107, 0,105,110,110,101,114, 95, 97,110,105,109, 91, 52, 93, 0,105,110,110,101,114, 95, 97,110, +105,109, 95,115,101,108, 91, 52, 93, 0,105,110,110,101,114, 95,107,101,121, 91, 52, 93, 0,105,110,110,101,114, 95,107,101,121, + 95,115,101,108, 91, 52, 93, 0,105,110,110,101,114, 95,100,114,105,118,101,110, 91, 52, 93, 0,105,110,110,101,114, 95,100,114, +105,118,101,110, 95,115,101,108, 91, 52, 93, 0,104,101, 97,100,101,114, 91, 52, 93, 0,115,104,111,119, 95,104,101, 97,100,101, +114, 0,119, 99,111,108, 95,114,101,103,117,108, 97,114, 0,119, 99,111,108, 95,116,111,111,108, 0,119, 99,111,108, 95,116,101, +120,116, 0,119, 99,111,108, 95,114, 97,100,105,111, 0,119, 99,111,108, 95,111,112,116,105,111,110, 0,119, 99,111,108, 95,116, +111,103,103,108,101, 0,119, 99,111,108, 95,110,117,109, 0,119, 99,111,108, 95,110,117,109,115,108,105,100,101,114, 0,119, 99, +111,108, 95,109,101,110,117, 0,119, 99,111,108, 95,112,117,108,108,100,111,119,110, 0,119, 99,111,108, 95,109,101,110,117, 95, + 98, 97, 99,107, 0,119, 99,111,108, 95,109,101,110,117, 95,105,116,101,109, 0,119, 99,111,108, 95,116,111,111,108,116,105,112, + 0,119, 99,111,108, 95, 98,111,120, 0,119, 99,111,108, 95,115, 99,114,111,108,108, 0,119, 99,111,108, 95,112,114,111,103,114, +101,115,115, 0,119, 99,111,108, 95,108,105,115,116, 95,105,116,101,109, 0,119, 99,111,108, 95,115,116, 97,116,101, 0,112, 97, +110,101,108, 0,105, 99,111,110,102,105,108,101, 91, 50, 53, 54, 93, 0,105, 99,111,110, 95, 97,108,112,104, 97, 0, 98, 97, 99, +107, 91, 52, 93, 0,116,105,116,108,101, 91, 52, 93, 0,116,101,120,116, 95,104,105, 91, 52, 93, 0,104,101, 97,100,101,114, 95, +116,105,116,108,101, 91, 52, 93, 0,104,101, 97,100,101,114, 95,116,101,120,116, 91, 52, 93, 0,104,101, 97,100,101,114, 95,116, +101,120,116, 95,104,105, 91, 52, 93, 0, 98,117,116,116,111,110, 91, 52, 93, 0, 98,117,116,116,111,110, 95,116,105,116,108,101, + 91, 52, 93, 0, 98,117,116,116,111,110, 95,116,101,120,116, 91, 52, 93, 0, 98,117,116,116,111,110, 95,116,101,120,116, 95,104, +105, 91, 52, 93, 0,108,105,115,116, 91, 52, 93, 0,108,105,115,116, 95,116,105,116,108,101, 91, 52, 93, 0,108,105,115,116, 95, +116,101,120,116, 91, 52, 93, 0,108,105,115,116, 95,116,101,120,116, 95,104,105, 91, 52, 93, 0,112, 97,110,101,108, 91, 52, 93, + 0,112, 97,110,101,108, 95,116,105,116,108,101, 91, 52, 93, 0,112, 97,110,101,108, 95,116,101,120,116, 91, 52, 93, 0,112, 97, +110,101,108, 95,116,101,120,116, 95,104,105, 91, 52, 93, 0,115,104, 97,100,101, 49, 91, 52, 93, 0,115,104, 97,100,101, 50, 91, + 52, 93, 0,104,105,108,105,116,101, 91, 52, 93, 0,103,114,105,100, 91, 52, 93, 0,119,105,114,101, 91, 52, 93, 0,115,101,108, +101, 99,116, 91, 52, 93, 0,108, 97,109,112, 91, 52, 93, 0,115,112,101, 97,107,101,114, 91, 52, 93, 0,101,109,112,116,121, 91, + 52, 93, 0, 99, 97,109,101,114, 97, 91, 52, 93, 0,112, 97,100, 91, 56, 93, 0, 97, 99,116,105,118,101, 91, 52, 93, 0,103,114, +111,117,112, 91, 52, 93, 0,103,114,111,117,112, 95, 97, 99,116,105,118,101, 91, 52, 93, 0,116,114, 97,110,115,102,111,114,109, + 91, 52, 93, 0,118,101,114,116,101,120, 91, 52, 93, 0,118,101,114,116,101,120, 95,115,101,108,101, 99,116, 91, 52, 93, 0,101, +100,103,101, 91, 52, 93, 0,101,100,103,101, 95,115,101,108,101, 99,116, 91, 52, 93, 0,101,100,103,101, 95,115,101, 97,109, 91, + 52, 93, 0,101,100,103,101, 95,115,104, 97,114,112, 91, 52, 93, 0,101,100,103,101, 95,102, 97, 99,101,115,101,108, 91, 52, 93, + 0,101,100,103,101, 95, 99,114,101, 97,115,101, 91, 52, 93, 0,102, 97, 99,101, 91, 52, 93, 0,102, 97, 99,101, 95,115,101,108, +101, 99,116, 91, 52, 93, 0,102, 97, 99,101, 95,100,111,116, 91, 52, 93, 0,101,120,116,114, 97, 95,101,100,103,101, 95,108,101, +110, 91, 52, 93, 0,101,120,116,114, 97, 95,102, 97, 99,101, 95, 97,110,103,108,101, 91, 52, 93, 0,101,120,116,114, 97, 95,102, + 97, 99,101, 95, 97,114,101, 97, 91, 52, 93, 0,112, 97,100, 51, 91, 52, 93, 0,110,111,114,109, 97,108, 91, 52, 93, 0,118,101, +114,116,101,120, 95,110,111,114,109, 97,108, 91, 52, 93, 0, 98,111,110,101, 95,115,111,108,105,100, 91, 52, 93, 0, 98,111,110, +101, 95,112,111,115,101, 91, 52, 93, 0,115,116,114,105,112, 91, 52, 93, 0,115,116,114,105,112, 95,115,101,108,101, 99,116, 91, + 52, 93, 0, 99,102,114, 97,109,101, 91, 52, 93, 0,110,117,114, 98, 95,117,108,105,110,101, 91, 52, 93, 0,110,117,114, 98, 95, +118,108,105,110,101, 91, 52, 93, 0, 97, 99,116, 95,115,112,108,105,110,101, 91, 52, 93, 0,110,117,114, 98, 95,115,101,108, 95, +117,108,105,110,101, 91, 52, 93, 0,110,117,114, 98, 95,115,101,108, 95,118,108,105,110,101, 91, 52, 93, 0,108, 97,115,116,115, +101,108, 95,112,111,105,110,116, 91, 52, 93, 0,104, 97,110,100,108,101, 95,102,114,101,101, 91, 52, 93, 0,104, 97,110,100,108, +101, 95, 97,117,116,111, 91, 52, 93, 0,104, 97,110,100,108,101, 95,118,101, 99,116, 91, 52, 93, 0,104, 97,110,100,108,101, 95, + 97,108,105,103,110, 91, 52, 93, 0,104, 97,110,100,108,101, 95, 97,117,116,111, 95, 99,108, 97,109,112,101,100, 91, 52, 93, 0, +104, 97,110,100,108,101, 95,115,101,108, 95,102,114,101,101, 91, 52, 93, 0,104, 97,110,100,108,101, 95,115,101,108, 95, 97,117, +116,111, 91, 52, 93, 0,104, 97,110,100,108,101, 95,115,101,108, 95,118,101, 99,116, 91, 52, 93, 0,104, 97,110,100,108,101, 95, +115,101,108, 95, 97,108,105,103,110, 91, 52, 93, 0,104, 97,110,100,108,101, 95,115,101,108, 95, 97,117,116,111, 95, 99,108, 97, +109,112,101,100, 91, 52, 93, 0,100,115, 95, 99,104, 97,110,110,101,108, 91, 52, 93, 0,100,115, 95,115,117, 98, 99,104, 97,110, +110,101,108, 91, 52, 93, 0, 99,111,110,115,111,108,101, 95,111,117,116,112,117,116, 91, 52, 93, 0, 99,111,110,115,111,108,101, + 95,105,110,112,117,116, 91, 52, 93, 0, 99,111,110,115,111,108,101, 95,105,110,102,111, 91, 52, 93, 0, 99,111,110,115,111,108, +101, 95,101,114,114,111,114, 91, 52, 93, 0, 99,111,110,115,111,108,101, 95, 99,117,114,115,111,114, 91, 52, 93, 0,118,101,114, +116,101,120, 95,115,105,122,101, 0,111,117,116,108,105,110,101, 95,119,105,100,116,104, 0,102, 97, 99,101,100,111,116, 95,115, +105,122,101, 0,110,111,111,100,108,101, 95, 99,117,114,118,105,110,103, 0,115,121,110,116, 97,120,108, 91, 52, 93, 0,115,121, +110,116, 97,120,110, 91, 52, 93, 0,115,121,110,116, 97,120, 98, 91, 52, 93, 0,115,121,110,116, 97,120,118, 91, 52, 93, 0,115, +121,110,116, 97,120, 99, 91, 52, 93, 0,109,111,118,105,101, 91, 52, 93, 0,109,111,118,105,101, 99,108,105,112, 91, 52, 93, 0, +105,109, 97,103,101, 91, 52, 93, 0,115, 99,101,110,101, 91, 52, 93, 0, 97,117,100,105,111, 91, 52, 93, 0,101,102,102,101, 99, +116, 91, 52, 93, 0,112,108,117,103,105,110, 91, 52, 93, 0,116,114, 97,110,115,105,116,105,111,110, 91, 52, 93, 0,109,101,116, + 97, 91, 52, 93, 0,101,100,105,116,109,101,115,104, 95, 97, 99,116,105,118,101, 91, 52, 93, 0,104, 97,110,100,108,101, 95,118, +101,114,116,101,120, 91, 52, 93, 0,104, 97,110,100,108,101, 95,118,101,114,116,101,120, 95,115,101,108,101, 99,116, 91, 52, 93, + 0,104, 97,110,100,108,101, 95,118,101,114,116,101,120, 95,115,105,122,101, 0,109, 97,114,107,101,114, 95,111,117,116,108,105, +110,101, 91, 52, 93, 0,109, 97,114,107,101,114, 91, 52, 93, 0, 97, 99,116, 95,109, 97,114,107,101,114, 91, 52, 93, 0,115,101, +108, 95,109, 97,114,107,101,114, 91, 52, 93, 0,100,105,115, 95,109, 97,114,107,101,114, 91, 52, 93, 0,108,111, 99,107, 95,109, + 97,114,107,101,114, 91, 52, 93, 0, 98,117,110,100,108,101, 95,115,111,108,105,100, 91, 52, 93, 0,112, 97,116,104, 95, 98,101, +102,111,114,101, 91, 52, 93, 0,112, 97,116,104, 95, 97,102,116,101,114, 91, 52, 93, 0, 99, 97,109,101,114, 97, 95,112, 97,116, +104, 91, 52, 93, 0,104,112, 97,100, 91, 55, 93, 0,112,114,101,118,105,101,119, 95, 98, 97, 99,107, 91, 52, 93, 0,112,114,101, +118,105,101,119, 95,115,116,105,116, 99,104, 95,102, 97, 99,101, 91, 52, 93, 0,112,114,101,118,105,101,119, 95,115,116,105,116, + 99,104, 95,101,100,103,101, 91, 52, 93, 0,112,114,101,118,105,101,119, 95,115,116,105,116, 99,104, 95,118,101,114,116, 91, 52, + 93, 0,112,114,101,118,105,101,119, 95,115,116,105,116, 99,104, 95,115,116,105,116, 99,104, 97, 98,108,101, 91, 52, 93, 0,112, +114,101,118,105,101,119, 95,115,116,105,116, 99,104, 95,117,110,115,116,105,116, 99,104, 97, 98,108,101, 91, 52, 93, 0,112,114, +101,118,105,101,119, 95,115,116,105,116, 99,104, 95, 97, 99,116,105,118,101, 91, 52, 93, 0,109, 97,116, 99,104, 91, 52, 93, 0, +115,101,108,101, 99,116,101,100, 95,104,105,103,104,108,105,103,104,116, 91, 52, 93, 0,115,111,108,105,100, 91, 52, 93, 0,116, +117,105, 0,116, 98,117,116,115, 0,116,118, 51,100, 0,116,102,105,108,101, 0,116,105,112,111, 0,116,105,110,102,111, 0,116, + 97, 99,116, 0,116,110,108, 97, 0,116,115,101,113, 0,116,105,109, 97, 0,116,101,120,116, 0,116,111,111,112,115, 0,116,116, +105,109,101, 0,116,110,111,100,101, 0,116,108,111,103,105, 99, 0,116,117,115,101,114,112,114,101,102, 0,116, 99,111,110,115, +111,108,101, 0,116, 99,108,105,112, 0,116, 97,114,109, 91, 50, 48, 93, 0, 97, 99,116,105,118,101, 95,116,104,101,109,101, 95, + 97,114,101, 97, 0,109,111,100,117,108,101, 91, 54, 52, 93, 0,115,112,101, 99, 91, 52, 93, 0,100,117,112,102,108, 97,103, 0, +115, 97,118,101,116,105,109,101, 0,116,101,109,112,100,105,114, 91, 55, 54, 56, 93, 0,102,111,110,116,100,105,114, 91, 55, 54, + 56, 93, 0,114,101,110,100,101,114,100,105,114, 91, 49, 48, 50, 52, 93, 0,116,101,120,116,117,100,105,114, 91, 55, 54, 56, 93, + 0,112,108,117,103,116,101,120,100,105,114, 91, 55, 54, 56, 93, 0,112,108,117,103,115,101,113,100,105,114, 91, 55, 54, 56, 93, + 0,112,121,116,104,111,110,100,105,114, 91, 55, 54, 56, 93, 0,115,111,117,110,100,100,105,114, 91, 55, 54, 56, 93, 0,105,109, + 97,103,101, 95,101,100,105,116,111,114, 91, 49, 48, 50, 52, 93, 0, 97,110,105,109, 95,112,108, 97,121,101,114, 91, 49, 48, 50, + 52, 93, 0, 97,110,105,109, 95,112,108, 97,121,101,114, 95,112,114,101,115,101,116, 0,118, 50,100, 95,109,105,110, 95,103,114, +105,100,115,105,122,101, 0,116,105,109,101, 99,111,100,101, 95,115,116,121,108,101, 0,118,101,114,115,105,111,110,115, 0,100, + 98,108, 95, 99,108,105, 99,107, 95,116,105,109,101, 0,103, 97,109,101,102,108, 97,103,115, 0,119,104,101,101,108,108,105,110, +101,115, 99,114,111,108,108, 0,117,105,102,108, 97,103, 0,108, 97,110,103,117, 97,103,101, 0,117,115,101,114,112,114,101,102, + 0,118,105,101,119,122,111,111,109, 0,109,105,120, 98,117,102,115,105,122,101, 0, 97,117,100,105,111,100,101,118,105, 99,101, + 0, 97,117,100,105,111,114, 97,116,101, 0, 97,117,100,105,111,102,111,114,109, 97,116, 0, 97,117,100,105,111, 99,104, 97,110, +110,101,108,115, 0,100,112,105, 0,101,110, 99,111,100,105,110,103, 0,116,114, 97,110,115,111,112,116,115, 0,109,101,110,117, +116,104,114,101,115,104,111,108,100, 49, 0,109,101,110,117,116,104,114,101,115,104,111,108,100, 50, 0,116,104,101,109,101,115, + 0,117,105,102,111,110,116,115, 0,117,105,115,116,121,108,101,115, 0,107,101,121,109, 97,112,115, 0,117,115,101,114, 95,107, +101,121,109, 97,112,115, 0, 97,100,100,111,110,115, 0,107,101,121, 99,111,110,102,105,103,115,116,114, 91, 54, 52, 93, 0,117, +110,100,111,115,116,101,112,115, 0,117,110,100,111,109,101,109,111,114,121, 0,103,112, 95,109, 97,110,104, 97,116,116,101,110, +100,105,115,116, 0,103,112, 95,101,117, 99,108,105,100,101, 97,110,100,105,115,116, 0,103,112, 95,101,114, 97,115,101,114, 0, +103,112, 95,115,101,116,116,105,110,103,115, 0,116, 98, 95,108,101,102,116,109,111,117,115,101, 0,116, 98, 95,114,105,103,104, +116,109,111,117,115,101, 0,108,105,103,104,116, 91, 51, 93, 0,116,119, 95,104,111,116,115,112,111,116, 0,116,119, 95,102,108, + 97,103, 0,116,119, 95,104, 97,110,100,108,101,115,105,122,101, 0,116,119, 95,115,105,122,101, 0,116,101,120,116,105,109,101, +111,117,116, 0,116,101,120, 99,111,108,108,101, 99,116,114, 97,116,101, 0,119,109,100,114, 97,119,109,101,116,104,111,100, 0, +100,114, 97,103,116,104,114,101,115,104,111,108,100, 0,109,101,109, 99, 97, 99,104,101,108,105,109,105,116, 0,112,114,101,102, +101,116, 99,104,102,114, 97,109,101,115, 0,102,114, 97,109,101,115,101,114,118,101,114,112,111,114,116, 0,112, 97,100, 95,114, +111,116, 95, 97,110,103,108,101, 0,111, 98, 99,101,110,116,101,114, 95,100,105, 97, 0,114,118,105,115,105,122,101, 0,114,118, +105, 98,114,105,103,104,116, 0,114,101, 99,101,110,116, 95,102,105,108,101,115, 0,115,109,111,111,116,104, 95,118,105,101,119, +116,120, 0,103,108,114,101,115,108,105,109,105,116, 0, 99,117,114,115,115,105,122,101, 0, 99,111,108,111,114, 95,112,105, 99, +107,101,114, 95,116,121,112,101, 0,105,112,111, 95,110,101,119, 0,107,101,121,104, 97,110,100,108,101,115, 95,110,101,119, 0, +115, 99,114, 99, 97,115,116,102,112,115, 0,115, 99,114, 99, 97,115,116,119, 97,105,116, 0,119,105,100,103,101,116, 95,117,110, +105,116, 0, 97,110,105,115,111,116,114,111,112,105, 99, 95,102,105,108,116,101,114, 0,117,115,101, 95, 49, 54, 98,105,116, 95, +116,101,120,116,117,114,101,115, 0,112, 97,100, 56, 0,110,100,111,102, 95,115,101,110,115,105,116,105,118,105,116,121, 0,110, +100,111,102, 95,102,108, 97,103, 0,103,108, 97,108,112,104, 97, 99,108,105,112, 0,116,101,120,116, 95,114,101,110,100,101,114, + 0,112, 97,100, 57, 0, 99,111, 98, 97, 95,119,101,105,103,104,116, 0,115, 99,117,108,112,116, 95,112, 97,105,110,116, 95,111, +118,101,114,108, 97,121, 95, 99,111,108, 91, 51, 93, 0,116,119,101, 97,107, 95,116,104,114,101,115,104,111,108,100, 0, 97,117, +116,104,111,114, 91, 56, 48, 93, 0, 99,111,109,112,117,116,101, 95,100,101,118,105, 99,101, 95,116,121,112,101, 0, 99,111,109, +112,117,116,101, 95,100,101,118,105, 99,101, 95,105,100, 0,102, 99,117, 95,105,110, 97, 99,116,105,118,101, 95, 97,108,112,104, + 97, 0,118,101,114,116, 98, 97,115,101, 0,101,100,103,101, 98, 97,115,101, 0, 97,114,101, 97, 98, 97,115,101, 0, 42,110,101, +119,115, 99,101,110,101, 0,114,101,100,114, 97,119,115, 95,102,108, 97,103, 0,102,117,108,108, 0,116,101,109,112, 0,119,105, +110,105,100, 0,100,111, 95,100,114, 97,119, 0,100,111, 95,114,101,102,114,101,115,104, 0,100,111, 95,100,114, 97,119, 95,103, +101,115,116,117,114,101, 0,100,111, 95,100,114, 97,119, 95,112, 97,105,110,116, 99,117,114,115,111,114, 0,100,111, 95,100,114, + 97,119, 95,100,114, 97,103, 0,115,119, 97,112, 0,109, 97,105,110,119,105,110, 0,115,117, 98,119,105,110, 97, 99,116,105,118, +101, 0, 42, 97,110,105,109,116,105,109,101,114, 0, 42, 99,111,110,116,101,120,116, 0,104, 97,110,100,108,101,114, 91, 56, 93, + 0, 42,110,101,119,118, 0,118,101, 99, 0, 42,118, 49, 0, 42,118, 50, 0, 42,116,121,112,101, 0,112, 97,110,101,108,110, 97, +109,101, 91, 54, 52, 93, 0,116, 97, 98,110, 97,109,101, 91, 54, 52, 93, 0,100,114, 97,119,110, 97,109,101, 91, 54, 52, 93, 0, +111,102,115,120, 0,111,102,115,121, 0,115,105,122,101,120, 0,115,105,122,101,121, 0,108, 97, 98,101,108,111,102,115, 0,114, +117,110,116,105,109,101, 95,102,108, 97,103, 0, 99,111,110,116,114,111,108, 0,115,110, 97,112, 0,115,111,114,116,111,114,100, +101,114, 0, 42,112, 97,110,101,108,116, 97, 98, 0, 42, 97, 99,116,105,118,101,100, 97,116, 97, 0,108,105,115,116, 95,115, 99, +114,111,108,108, 0,108,105,115,116, 95,115,105,122,101, 0,108,105,115,116, 95,108, 97,115,116, 95,108,101,110, 0,108,105,115, +116, 95,103,114,105,112, 95,115,105,122,101, 0,108,105,115,116, 95,115,101, 97,114, 99,104, 91, 54, 52, 93, 0, 42,118, 51, 0, + 42,118, 52, 0, 42,102,117,108,108, 0, 98,117,116,115,112, 97, 99,101,116,121,112,101, 0,104,101, 97,100,101,114,116,121,112, +101, 0,115,112, 97, 99,101,100, 97,116, 97, 0,104, 97,110,100,108,101,114,115, 0, 97, 99,116,105,111,110,122,111,110,101,115, + 0,119,105,110,114, 99,116, 0,100,114, 97,119,114, 99,116, 0,115,119,105,110,105,100, 0,114,101,103,105,111,110,116,121,112, +101, 0, 97,108,105,103,110,109,101,110,116, 0,100,111, 95,100,114, 97,119, 95,111,118,101,114,108, 97,121, 0,117,105, 98,108, +111, 99,107,115, 0,112, 97,110,101,108,115, 0, 42,104,101, 97,100,101,114,115,116,114, 0, 42,114,101,103,105,111,110,100, 97, +116, 97, 0,115,117, 98,118,115,116,114, 91, 52, 93, 0,115,117, 98,118,101,114,115,105,111,110, 0,112, 97,100,115, 0,109,105, +110,118,101,114,115,105,111,110, 0,109,105,110,115,117, 98,118,101,114,115,105,111,110, 0,119,105,110,112,111,115, 0, 42, 99, +117,114,115, 99,114,101,101,110, 0, 42, 99,117,114,115, 99,101,110,101, 0,102,105,108,101,102,108, 97,103,115, 0,103,108,111, + 98, 97,108,102, 0,114,101,118,105,115,105,111,110, 0,110, 97,109,101, 91, 50, 53, 54, 93, 0,111,114,105,103, 95,119,105,100, +116,104, 0,111,114,105,103, 95,104,101,105,103,104,116, 0, 98,111,116,116,111,109, 0,114,105,103,104,116, 0,120,111,102,115, + 0,121,111,102,115, 0,108,105,102,116, 91, 51, 93, 0,103, 97,109,109, 97, 91, 51, 93, 0,103, 97,105,110, 91, 51, 93, 0,100, +105,114, 91, 55, 54, 56, 93, 0,116, 99, 0, 98,117,105,108,100, 95,115,105,122,101, 95,102,108, 97,103,115, 0, 98,117,105,108, +100, 95,116, 99, 95,102,108, 97,103,115, 0,100,111,110,101, 0,115,116, 97,114,116,115,116,105,108,108, 0,101,110,100,115,116, +105,108,108, 0, 42,115,116,114,105,112,100, 97,116, 97, 0, 42, 99,114,111,112, 0, 42,116,114, 97,110,115,102,111,114,109, 0, + 42, 99,111,108,111,114, 95, 98, 97,108, 97,110, 99,101, 0, 42,105,110,115,116, 97,110, 99,101, 95,112,114,105,118, 97,116,101, + 95,100, 97,116, 97, 0, 42, 42, 99,117,114,114,101,110,116, 95,112,114,105,118, 97,116,101, 95,100, 97,116, 97, 0, 42,116,109, +112, 0,115,116, 97,114,116,111,102,115, 0,101,110,100,111,102,115, 0,109, 97, 99,104,105,110,101, 0,115,116, 97,114,116,100, +105,115,112, 0,101,110,100,100,105,115,112, 0,115, 97,116, 0,109,117,108, 0,104, 97,110,100,115,105,122,101, 0, 97,110,105, +109, 95,112,114,101,115,101,101,107, 0,115,116,114,101, 97,109,105,110,100,101,120, 0,109,117,108,116,105, 99, 97,109, 95,115, +111,117,114, 99,101, 0, 99,108,105,112, 95,102,108, 97,103, 0, 42,115,116,114,105,112, 0, 42,115, 99,101,110,101, 95, 99, 97, +109,101,114, 97, 0,101,102,102,101, 99,116, 95,102, 97,100,101,114, 0,115,112,101,101,100, 95,102, 97,100,101,114, 0, 42,115, +101,113, 49, 0, 42,115,101,113, 50, 0, 42,115,101,113, 51, 0,115,101,113, 98, 97,115,101, 0, 42,115,111,117,110,100, 0, 42, +115, 99,101,110,101, 95,115,111,117,110,100, 0,112,105,116, 99,104, 0,112, 97,110, 0,115,116,114,111, 98,101, 0, 42,101,102, +102,101, 99,116,100, 97,116, 97, 0, 97,110,105,109, 95,115,116, 97,114,116,111,102,115, 0, 97,110,105,109, 95,101,110,100,111, +102,115, 0, 98,108,101,110,100, 95,109,111,100,101, 0, 98,108,101,110,100, 95,111,112, 97, 99,105,116,121, 0, 42,111,108,100, + 98, 97,115,101,112, 0, 42,112, 97,114,115,101,113, 0, 42,115,101,113, 98, 97,115,101,112, 0,109,101,116, 97,115,116, 97, 99, +107, 0, 42, 97, 99,116, 95,115,101,113, 0, 97, 99,116, 95,105,109, 97,103,101,100,105,114, 91, 49, 48, 50, 52, 93, 0, 97, 99, +116, 95,115,111,117,110,100,100,105,114, 91, 49, 48, 50, 52, 93, 0,111,118,101,114, 95,111,102,115, 0,111,118,101,114, 95, 99, +102,114, 97, 0,111,118,101,114, 95,102,108, 97,103, 0,111,118,101,114, 95, 98,111,114,100,101,114, 0,101,100,103,101, 87,105, +100,116,104, 0,102,111,114,119, 97,114,100, 0,119,105,112,101,116,121,112,101, 0,102, 77,105,110,105, 0,102, 67,108, 97,109, +112, 0,102, 66,111,111,115,116, 0,100, 68,105,115,116, 0,100, 81,117, 97,108,105,116,121, 0, 98, 78,111, 67,111,109,112, 0, + 83, 99, 97,108,101,120, 73,110,105, 0, 83, 99, 97,108,101,121, 73,110,105, 0,120, 73,110,105, 0,121, 73,110,105, 0,114,111, +116, 73,110,105, 0,105,110,116,101,114,112,111,108, 97,116,105,111,110, 0,117,110,105,102,111,114,109, 95,115, 99, 97,108,101, + 0, 42,102,114, 97,109,101, 77, 97,112, 0,103,108,111, 98, 97,108, 83,112,101,101,100, 0,108, 97,115,116, 86, 97,108,105,100, + 70,114, 97,109,101, 0, 98,117,116,116,121,112,101, 0,117,115,101,114,106,105,116, 0,115,116, 97, 0,116,111,116,112, 97,114, +116, 0,110,111,114,109,102, 97, 99, 0,111, 98,102, 97, 99, 0,114, 97,110,100,102, 97, 99, 0,116,101,120,102, 97, 99, 0,114, + 97,110,100,108,105,102,101, 0,102,111,114, 99,101, 91, 51, 93, 0,118,101, 99,116,115,105,122,101, 0,109, 97,120,108,101,110, + 0,100,101,102,118,101, 99, 91, 51, 93, 0,109,117,108,116, 91, 52, 93, 0,108,105,102,101, 91, 52, 93, 0, 99,104,105,108,100, + 91, 52, 93, 0,109, 97,116, 91, 52, 93, 0,116,101,120,109, 97,112, 0, 99,117,114,109,117,108,116, 0,115,116, 97,116,105, 99, +115,116,101,112, 0,111,109, 97,116, 0,116,105,109,101,116,101,120, 0,115,112,101,101,100,116,101,120, 0,102,108, 97,103, 50, +110,101,103, 0,118,101,114,116,103,114,111,117,112, 95,118, 0,118,103,114,111,117,112,110, 97,109,101, 91, 54, 52, 93, 0,118, +103,114,111,117,112,110, 97,109,101, 95,118, 91, 54, 52, 93, 0, 42,107,101,121,115, 0,109,105,110,102, 97, 99, 0,110,114, 0, +117,115,101,100, 0,117,115,101,100,101,108,101,109, 0, 42,112,111,105,110, 0,114,101,115,101,116,100,105,115,116, 0,108, 97, +115,116,118, 97,108, 0, 42,109, 97, 0,107,101,121, 0,113,117, 97,108, 0,113,117, 97,108, 50, 0,116, 97,114,103,101,116, 78, + 97,109,101, 91, 54, 52, 93, 0,116,111,103,103,108,101, 78, 97,109,101, 91, 54, 52, 93, 0,118, 97,108,117,101, 91, 54, 52, 93, + 0,109, 97,120,118, 97,108,117,101, 91, 54, 52, 93, 0,100,101,108, 97,121, 0,100,117,114, 97,116,105,111,110, 0,109, 97,116, +101,114,105, 97,108, 78, 97,109,101, 91, 54, 52, 93, 0,100, 97,109,112,116,105,109,101,114, 0,112,114,111,112,110, 97,109,101, + 91, 54, 52, 93, 0,109, 97,116,110, 97,109,101, 91, 54, 52, 93, 0, 97,120,105,115,102,108, 97,103, 0,112,111,115,101, 99,104, + 97,110,110,101,108, 91, 54, 52, 93, 0, 99,111,110,115,116,114, 97,105,110,116, 91, 54, 52, 93, 0, 42,102,114,111,109, 79, 98, +106,101, 99,116, 0,115,117, 98,106,101, 99,116, 91, 54, 52, 93, 0, 98,111,100,121, 91, 54, 52, 93, 0,111,116,121,112,101, 0, +112,117,108,115,101, 0,102,114,101,113, 0,116,111,116,108,105,110,107,115, 0, 42, 42,108,105,110,107,115, 0,116, 97,112, 0, +106,111,121,105,110,100,101,120, 0, 97,120,105,115, 95,115,105,110,103,108,101, 0, 97,120,105,115,102, 0, 98,117,116,116,111, +110, 0,104, 97,116, 0,104, 97,116,102, 0,112,114,101, 99,105,115,105,111,110, 0,115,116,114, 91, 49, 50, 56, 93, 0, 42,109, +121,110,101,119, 0,105,110,112,117,116,115, 0,116,111,116,115,108,105,110,107,115, 0, 42, 42,115,108,105,110,107,115, 0,118, + 97,108,111, 0,115,116, 97,116,101, 95,109, 97,115,107, 0, 42, 97, 99,116, 0,102,114, 97,109,101, 80,114,111,112, 91, 54, 52, + 93, 0, 98,108,101,110,100,105,110, 0,112,114,105,111,114,105,116,121, 0,101,110,100, 95,114,101,115,101,116, 0,115,116,114, +105,100,101, 97,120,105,115, 0,115,116,114,105,100,101,108,101,110,103,116,104, 0,108, 97,121,101,114, 95,119,101,105,103,104, +116, 0,109,105,110, 95,103, 97,105,110, 0,109, 97,120, 95,103, 97,105,110, 0,114,101,102,101,114,101,110, 99,101, 95,100,105, +115,116, 97,110, 99,101, 0,109, 97,120, 95,100,105,115,116, 97,110, 99,101, 0,114,111,108,108,111,102,102, 95,102, 97, 99,116, +111,114, 0, 99,111,110,101, 95,105,110,110,101,114, 95, 97,110,103,108,101, 0, 99,111,110,101, 95,111,117,116,101,114, 95, 97, +110,103,108,101, 0, 99,111,110,101, 95,111,117,116,101,114, 95,103, 97,105,110, 0,115,110,100,110,114, 0,115,111,117,110,100, + 51, 68, 0,112, 97,100, 54, 91, 49, 93, 0, 42,109,101, 0,108,105,110, 86,101,108,111, 99,105,116,121, 91, 51, 93, 0, 97,110, +103, 86,101,108,111, 99,105,116,121, 91, 51, 93, 0,108,111, 99, 97,108,102,108, 97,103, 0,100,121,110, 95,111,112,101,114, 97, +116,105,111,110, 0,102,111,114, 99,101,108,111, 99, 91, 51, 93, 0,102,111,114, 99,101,114,111,116, 91, 51, 93, 0,112, 97,100, + 49, 91, 51, 93, 0,108,105,110,101, 97,114,118,101,108,111, 99,105,116,121, 91, 51, 93, 0, 97,110,103,117,108, 97,114,118,101, +108,111, 99,105,116,121, 91, 51, 93, 0, 42,114,101,102,101,114,101,110, 99,101, 0,109,105,110, 0,109, 97,120, 0,114,111,116, +100, 97,109,112, 0,109,105,110,108,111, 99, 91, 51, 93, 0,109, 97,120,108,111, 99, 91, 51, 93, 0,109,105,110,114,111,116, 91, + 51, 93, 0,109, 97,120,114,111,116, 91, 51, 93, 0,109, 97,116,112,114,111,112, 91, 54, 52, 93, 0, 98,117,116,115,116, 97, 0, + 98,117,116,101,110,100, 0,100,105,115,116,114,105, 98,117,116,105,111,110, 0,105,110,116, 95, 97,114,103, 95, 49, 0,105,110, +116, 95, 97,114,103, 95, 50, 0,102,108,111, 97,116, 95, 97,114,103, 95, 49, 0,102,108,111, 97,116, 95, 97,114,103, 95, 50, 0, +116,111, 80,114,111,112, 78, 97,109,101, 91, 54, 52, 93, 0, 42,116,111, 79, 98,106,101, 99,116, 0, 98,111,100,121, 84,121,112, +101, 0,102,105,108,101,110, 97,109,101, 91, 54, 52, 93, 0,108,111, 97,100, 97,110,105,110, 97,109,101, 91, 54, 52, 93, 0,105, +110,116, 95, 97,114,103, 0,102,108,111, 97,116, 95, 97,114,103, 0,105,110,102,108,117,101,110, 99,101, 0, 42,115,117, 98,116, + 97,114,103,101,116, 0,102, 97, 99,105,110,103, 97,120,105,115, 0,118,101,108,111, 99,105,116,121, 0, 97, 99, 99,101,108,101, +114, 97,116,105,111,110, 0,116,117,114,110,115,112,101,101,100, 0,117,112,100, 97,116,101, 84,105,109,101, 0, 42,110, 97,118, +109,101,115,104, 0,103,111, 0, 42,110,101,119,112, 97, 99,107,101,100,102,105,108,101, 0, 97,116,116,101,110,117, 97,116,105, +111,110, 0,100,105,115,116, 97,110, 99,101, 0, 42, 99, 97, 99,104,101, 0, 42,119, 97,118,101,102,111,114,109, 0, 42,112,108, + 97,121, 98, 97, 99,107, 95,104, 97,110,100,108,101, 0, 42,108, 97,109,112,114,101,110, 0,103,111, 98,106,101, 99,116, 0,100, +117,112,108,105, 95,111,102,115, 91, 51, 93, 0, 42,112,114,111,112, 0, 99,104,105,108,100, 98, 97,115,101, 0,114,111,108,108, + 0,104,101, 97,100, 91, 51, 93, 0,116, 97,105,108, 91, 51, 93, 0, 98,111,110,101, 95,109, 97,116, 91, 51, 93, 91, 51, 93, 0, + 97,114,109, 95,104,101, 97,100, 91, 51, 93, 0, 97,114,109, 95,116, 97,105,108, 91, 51, 93, 0, 97,114,109, 95,109, 97,116, 91, + 52, 93, 91, 52, 93, 0, 97,114,109, 95,114,111,108,108, 0,120,119,105,100,116,104, 0,122,119,105,100,116,104, 0,101, 97,115, +101, 49, 0,101, 97,115,101, 50, 0,114, 97,100, 95,104,101, 97,100, 0,114, 97,100, 95,116, 97,105,108, 0,112, 97,100, 91, 49, + 93, 0, 98,111,110,101, 98, 97,115,101, 0, 99,104, 97,105,110, 98, 97,115,101, 0, 42,101,100, 98,111, 0, 42, 97, 99,116, 95, + 98,111,110,101, 0, 42, 97, 99,116, 95,101,100, 98,111,110,101, 0, 42,115,107,101,116, 99,104, 0,103,101,118,101,114,116,100, +101,102,111,114,109,101,114, 0,108, 97,121,101,114, 95,117,115,101,100, 0,108, 97,121,101,114, 95,112,114,111,116,101, 99,116, +101,100, 0,103,104,111,115,116,101,112, 0,103,104,111,115,116,115,105,122,101, 0,103,104,111,115,116,116,121,112,101, 0,112, + 97,116,104,115,105,122,101, 0,103,104,111,115,116,115,102, 0,103,104,111,115,116,101,102, 0,112, 97,116,104,115,102, 0,112, + 97,116,104,101,102, 0,112, 97,116,104, 98, 99, 0,112, 97,116,104, 97, 99, 0, 42,112,111,105,110,116,115, 0,115,116, 97,114, +116, 95,102,114, 97,109,101, 0,101,110,100, 95,102,114, 97,109,101, 0,103,104,111,115,116, 95,115,102, 0,103,104,111,115,116, + 95,101,102, 0,103,104,111,115,116, 95, 98, 99, 0,103,104,111,115,116, 95, 97, 99, 0,103,104,111,115,116, 95,116,121,112,101, + 0,103,104,111,115,116, 95,115,116,101,112, 0,103,104,111,115,116, 95,102,108, 97,103, 0,112, 97,116,104, 95,116,121,112,101, + 0,112, 97,116,104, 95,115,116,101,112, 0,112, 97,116,104, 95,118,105,101,119,102,108, 97,103, 0,112, 97,116,104, 95, 98, 97, +107,101,102,108, 97,103, 0,112, 97,116,104, 95,115,102, 0,112, 97,116,104, 95,101,102, 0,112, 97,116,104, 95, 98, 99, 0,112, + 97,116,104, 95, 97, 99, 0,105,107,102,108, 97,103, 0, 97,103,114,112, 95,105,110,100,101,120, 0, 99,111,110,115,116,102,108, + 97,103, 0,115,101,108,101, 99,116,102,108, 97,103, 0,112, 97,100, 48, 91, 54, 93, 0, 42, 98,111,110,101, 0, 42, 99,104,105, +108,100, 0,105,107,116,114,101,101, 0,115,105,107,116,114,101,101, 0, 42, 99,117,115,116,111,109, 0, 42, 99,117,115,116,111, +109, 95,116,120, 0,101,117,108, 91, 51, 93, 0, 99,104, 97,110, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,101, 95, +109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,101, 95,104,101, 97,100, 91, 51, 93, 0,112,111,115,101, 95,116, 97,105,108, + 91, 51, 93, 0,108,105,109,105,116,109,105,110, 91, 51, 93, 0,108,105,109,105,116,109, 97,120, 91, 51, 93, 0,115,116,105,102, +102,110,101,115,115, 91, 51, 93, 0,105,107,115,116,114,101,116, 99,104, 0,105,107,114,111,116,119,101,105,103,104,116, 0,105, +107,108,105,110,119,101,105,103,104,116, 0, 42,116,101,109,112, 0, 99,104, 97,110, 98, 97,115,101, 0, 42, 99,104, 97,110,104, + 97,115,104, 0,112,114,111,120,121, 95,108, 97,121,101,114, 0,115,116,114,105,100,101, 95,111,102,102,115,101,116, 91, 51, 93, + 0, 99,121, 99,108,105, 99, 95,111,102,102,115,101,116, 91, 51, 93, 0, 97,103,114,111,117,112,115, 0, 97, 99,116,105,118,101, + 95,103,114,111,117,112, 0,105,107,115,111,108,118,101,114, 0, 42,105,107,100, 97,116, 97, 0, 42,105,107,112, 97,114, 97,109, + 0,112,114,111,120,121, 95, 97, 99,116, 95, 98,111,110,101, 91, 54, 52, 93, 0,110,117,109,105,116,101,114, 0,110,117,109,115, +116,101,112, 0,109,105,110,115,116,101,112, 0,109, 97,120,115,116,101,112, 0,115,111,108,118,101,114, 0,102,101,101,100, 98, + 97, 99,107, 0,109, 97,120,118,101,108, 0,100, 97,109,112,109, 97,120, 0,100, 97,109,112,101,112,115, 0, 99,104, 97,110,110, +101,108,115, 0, 99,117,115,116,111,109, 67,111,108, 0, 99,115, 0, 99,117,114,118,101,115, 0,103,114,111,117,112,115, 0, 97, + 99,116,105,118,101, 95,109, 97,114,107,101,114, 0,105,100,114,111,111,116, 0, 42,115,111,117,114, 99,101, 0, 42,102,105,108, +116,101,114, 95,103,114,112, 0,115,101, 97,114, 99,104,115,116,114, 91, 54, 52, 93, 0,102,105,108,116,101,114,102,108, 97,103, + 0,114,101,110, 97,109,101, 73,110,100,101,120, 0, 97,100,115, 0,116,105,109,101,115,108,105,100,101, 0, 42,103,114,112, 0, +110, 97,109,101, 91, 51, 48, 93, 0,111,119,110,115,112, 97, 99,101, 0,116, 97,114,115,112, 97, 99,101, 0,101,110,102,111,114, + 99,101, 0,104,101, 97,100,116, 97,105,108, 0,108,105,110, 95,101,114,114,111,114, 0,114,111,116, 95,101,114,114,111,114, 0, + 42,116, 97,114, 0,109, 97,116,114,105,120, 91, 52, 93, 91, 52, 93, 0,115,112, 97, 99,101, 0,114,111,116, 79,114,100,101,114, + 0,116, 97,114,110,117,109, 0,116, 97,114,103,101,116,115, 0,105,116,101,114, 97,116,105,111,110,115, 0,114,111,111,116, 98, +111,110,101, 0,109, 97,120, 95,114,111,111,116, 98,111,110,101, 0, 42,112,111,108,101,116, 97,114, 0,112,111,108,101,115,117, + 98,116, 97,114,103,101,116, 91, 54, 52, 93, 0,112,111,108,101, 97,110,103,108,101, 0,111,114,105,101,110,116,119,101,105,103, +104,116, 0,103,114, 97, 98,116, 97,114,103,101,116, 91, 51, 93, 0,110,117,109,112,111,105,110,116,115, 0, 99,104, 97,105,110, +108,101,110, 0,120,122, 83, 99, 97,108,101, 77,111,100,101, 0,114,101,115,101,114,118,101,100, 49, 0,114,101,115,101,114,118, +101,100, 50, 0,109,105,110,109, 97,120,102,108, 97,103, 0,115,116,117, 99,107, 0, 99, 97, 99,104,101, 91, 51, 93, 0,108,111, + 99,107,102,108, 97,103, 0,102,111,108,108,111,119,102,108, 97,103, 0,118,111,108,109,111,100,101, 0,112,108, 97,110,101, 0, +111,114,103,108,101,110,103,116,104, 0, 98,117,108,103,101, 0,112,105,118, 88, 0,112,105,118, 89, 0,112,105,118, 90, 0, 97, +120, 88, 0, 97,120, 89, 0, 97,120, 90, 0,109,105,110, 76,105,109,105,116, 91, 54, 93, 0,109, 97,120, 76,105,109,105,116, 91, + 54, 93, 0,101,120,116,114, 97, 70,122, 0,105,110,118,109, 97,116, 91, 52, 93, 91, 52, 93, 0,102,114,111,109, 0,116,111, 0, +109, 97,112, 91, 51, 93, 0,101,120,112,111, 0,102,114,111,109, 95,109,105,110, 91, 51, 93, 0,102,114,111,109, 95,109, 97,120, + 91, 51, 93, 0,116,111, 95,109,105,110, 91, 51, 93, 0,116,111, 95,109, 97,120, 91, 51, 93, 0,114,111,116, 65,120,105,115, 0, +122,109,105,110, 0,122,109, 97,120, 0,112, 97,100, 91, 57, 93, 0,116,114, 97, 99,107, 91, 54, 52, 93, 0,111, 98,106,101, 99, +116, 91, 54, 52, 93, 0, 42,100,101,112,116,104, 95,111, 98, 0, 99,104, 97,110,110,101,108, 91, 51, 50, 93, 0,110,111, 95,114, +111,116, 95, 97,120,105,115, 0,115,116,114,105,100,101, 95, 97,120,105,115, 0, 99,117,114,109,111,100, 0, 97, 99,116,115,116, + 97,114,116, 0, 97, 99,116,101,110,100, 0, 97, 99,116,111,102,102,115, 0,115,116,114,105,100,101,108,101,110, 0, 98,108,101, +110,100,111,117,116, 0,115,116,114,105,100,101, 99,104, 97,110,110,101,108, 91, 51, 50, 93, 0,111,102,102,115, 95, 98,111,110, +101, 91, 51, 50, 93, 0,104, 97,115,105,110,112,117,116, 0,104, 97,115,111,117,116,112,117,116, 0,100, 97,116, 97,116,121,112, +101, 0,115,111, 99,107,101,116,116,121,112,101, 0,105,115, 95, 99,111,112,121, 0,101,120,116,101,114,110, 97,108, 0, 42,110, +101,119, 95,115,111, 99,107, 0, 42,115,116,111,114, 97,103,101, 0,108,105,109,105,116, 0,115,116,114,117, 99,116, 95,116,121, +112,101, 0,108,111, 99,120, 0,108,111, 99,121, 0, 42,100,101,102, 97,117,108,116, 95,118, 97,108,117,101, 0,115,116, 97, 99, +107, 95,105,110,100,101,120, 0,115,116, 97, 99,107, 95,116,121,112,101, 0,111,119,110, 95,105,110,100,101,120, 0,116,111, 95, +105,110,100,101,120, 0, 42,103,114,111,117,112,115,111, 99,107, 0, 42,108,105,110,107, 0,110,115, 0, 42,114,101, 99,116, 0, +120,115,105,122,101, 0,121,115,105,122,101, 0, 42,110,101,119, 95,110,111,100,101, 0,108, 97,115,116,121, 0,111,117,116,112, +117,116,115, 0,109,105,110,105,119,105,100,116,104, 0,117,112,100, 97,116,101, 0,108, 97, 98,101,108, 91, 54, 52, 93, 0, 99, +117,115,116,111,109, 49, 0, 99,117,115,116,111,109, 50, 0, 99,117,115,116,111,109, 51, 0, 99,117,115,116,111,109, 52, 0,110, +101,101,100, 95,101,120,101, 99, 0,101,120,101, 99, 0, 42,116,104,114,101, 97,100,100, 97,116, 97, 0,116,111,116,114, 0, 98, +117,116,114, 0,112,114,118,114, 0, 42, 98,108,111, 99,107, 0, 42,116,121,112,101,105,110,102,111, 0, 42,102,114,111,109,110, +111,100,101, 0, 42,116,111,110,111,100,101, 0, 42,102,114,111,109,115,111, 99,107, 0, 42,116,111,115,111, 99,107, 0,110,111, +100,101,115, 0,108,105,110,107,115, 0,105,110,105,116, 0, 99,117,114, 95,105,110,100,101,120, 0,110,111,100,101,116,121,112, +101, 0, 42,101,120,101, 99,100, 97,116, 97, 0, 40, 42,112,114,111,103,114,101,115,115, 41, 40, 41, 0, 40, 42,115,116, 97,116, +115, 95,100,114, 97,119, 41, 40, 41, 0, 40, 42,116,101,115,116, 95, 98,114,101, 97,107, 41, 40, 41, 0, 42,116, 98,104, 0, 42, +112,114,104, 0, 42,115,100,104, 0,118, 97,108,117,101, 91, 51, 93, 0,118, 97,108,117,101, 91, 52, 93, 0, 99,121, 99,108,105, + 99, 0,109,111,118,105,101, 0,115, 97,109,112,108,101,115, 0,109, 97,120,115,112,101,101,100, 0,109,105,110,115,112,101,101, +100, 0, 99,117,114,118,101,100, 0,112,101,114, 99,101,110,116,120, 0,112,101,114, 99,101,110,116,121, 0, 98,111,107,101,104, + 0,103, 97,109,109, 97, 0,105,109, 97,103,101, 95,105,110, 95,119,105,100,116,104, 0,105,109, 97,103,101, 95,105,110, 95,104, +101,105,103,104,116, 0, 99,101,110,116,101,114, 95,120, 0, 99,101,110,116,101,114, 95,121, 0,115,112,105,110, 0,119,114, 97, +112, 0,115,105,103,109, 97, 95, 99,111,108,111,114, 0,115,105,103,109, 97, 95,115,112, 97, 99,101, 0,104,117,101, 0, 98, 97, +115,101, 95,112, 97,116,104, 91, 49, 48, 50, 52, 93, 0,102,111,114,109, 97,116, 0, 97, 99,116,105,118,101, 95,105,110,112,117, +116, 0,117,115,101, 95,114,101,110,100,101,114, 95,102,111,114,109, 97,116, 0,117,115,101, 95,110,111,100,101, 95,102,111,114, +109, 97,116, 0,116, 49, 0,116, 50, 0,116, 51, 0,102,115,116,114,101,110,103,116,104, 0,102, 97,108,112,104, 97, 0,107,101, +121, 91, 52, 93, 0, 97,108,103,111,114,105,116,104,109, 0, 99,104, 97,110,110,101,108, 0,120, 49, 0,120, 50, 0,121, 49, 0, +121, 50, 0,102, 97, 99, 95,120, 49, 0,102, 97, 99, 95,120, 50, 0,102, 97, 99, 95,121, 49, 0,102, 97, 99, 95,121, 50, 0, 99, +111,108,110, 97,109,101, 91, 54, 52, 93, 0, 98,107,116,121,112,101, 0,112, 97,100, 95, 99, 49, 0,103, 97,109, 99,111, 0,110, +111, 95,122, 98,117,102, 0,102,115,116,111,112, 0,109, 97,120, 98,108,117,114, 0, 98,116,104,114,101,115,104, 0,114,111,116, + 97,116,105,111,110, 0,112, 97,100, 95,102, 49, 0, 42,100,105, 99,116, 0, 42,110,111,100,101, 0, 99,111,108,109,111,100, 0, +109,105,120, 0,102, 97,100,101, 0, 97,110,103,108,101, 95,111,102,115, 0,109, 0, 99, 0,106,105,116, 0,112,114,111,106, 0, +102,105,116, 0,115,108,111,112,101, 91, 51, 93, 0,112,111,119,101,114, 91, 51, 93, 0,108,105,102,116, 95,108,103,103, 91, 51, + 93, 0,103, 97,109,109, 97, 95,105,110,118, 91, 51, 93, 0,108,105,109, 99,104, 97,110, 0,117,110,115,112,105,108,108, 0,108, +105,109,115, 99, 97,108,101, 0,117,115,112,105,108,108,114, 0,117,115,112,105,108,108,103, 0,117,115,112,105,108,108, 98, 0, +116,101,120, 95,109, 97,112,112,105,110,103, 0, 99,111,108,111,114, 95,109, 97,112,112,105,110,103, 0,115,117,110, 95,100,105, +114,101, 99,116,105,111,110, 91, 51, 93, 0,116,117,114, 98,105,100,105,116,121, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, + 0,112,114,111,106,101, 99,116,105,111,110, 0,103,114, 97,100,105,101,110,116, 95,116,121,112,101, 0, 99,111,108,111,114,105, +110,103, 0,109,117,115,103,114, 97,118,101, 95,116,121,112,101, 0,119, 97,118,101, 95,116,121,112,101, 0,115,104,111,114,116, +121, 0,109,105,110,116, 97, 98,108,101, 0,109, 97,120,116, 97, 98,108,101, 0,101,120,116, 95,105,110, 91, 50, 93, 0,101,120, +116, 95,111,117,116, 91, 50, 93, 0, 42, 99,117,114,118,101, 0, 42,116, 97, 98,108,101, 0, 42,112,114,101,109,117,108,116, 97, + 98,108,101, 0,112,114,101,115,101,116, 0, 99,104, 97,110,103,101,100, 95,116,105,109,101,115,116, 97,109,112, 0, 99,117,114, +114, 0, 99,108,105,112,114, 0, 99,109, 91, 52, 93, 0, 98,108, 97, 99,107, 91, 51, 93, 0,119,104,105,116,101, 91, 51, 93, 0, + 98,119,109,117,108, 91, 51, 93, 0,115, 97,109,112,108,101, 91, 51, 93, 0,120, 95,114,101,115,111,108,117,116,105,111,110, 0, +100, 97,116, 97, 95,114, 91, 50, 53, 54, 93, 0,100, 97,116, 97, 95,103, 91, 50, 53, 54, 93, 0,100, 97,116, 97, 95, 98, 91, 50, + 53, 54, 93, 0,100, 97,116, 97, 95,108,117,109, 97, 91, 50, 53, 54, 93, 0,115, 97,109,112,108,101, 95,102,117,108,108, 0,115, + 97,109,112,108,101, 95,108,105,110,101,115, 0, 97, 99, 99,117,114, 97, 99,121, 0,119, 97,118,101,102,114,109, 95,109,111,100, +101, 0,119, 97,118,101,102,114,109, 95, 97,108,112,104, 97, 0,119, 97,118,101,102,114,109, 95,121,102, 97, 99, 0,119, 97,118, +101,102,114,109, 95,104,101,105,103,104,116, 0,118,101, 99,115, 99,111,112,101, 95, 97,108,112,104, 97, 0,118,101, 99,115, 99, +111,112,101, 95,104,101,105,103,104,116, 0,109,105,110,109, 97,120, 91, 51, 93, 91, 50, 93, 0,104,105,115,116, 0, 42,119, 97, +118,101,102,111,114,109, 95, 49, 0, 42,119, 97,118,101,102,111,114,109, 95, 50, 0, 42,119, 97,118,101,102,111,114,109, 95, 51, + 0, 42,118,101, 99,115, 99,111,112,101, 0,119, 97,118,101,102,111,114,109, 95,116,111,116, 0,111,102,102,115,101,116, 91, 50, + 93, 0, 99,108,111,110,101, 0,109,116,101,120, 0, 42,105, 99,111,110, 95,105,109, 98,117,102, 0,105, 99,111,110, 95,102,105, +108,101,112, 97,116,104, 91, 49, 48, 50, 52, 93, 0,110,111,114,109, 97,108, 95,119,101,105,103,104,116, 0,111, 98, 95,109,111, +100,101, 0,106,105,116,116,101,114, 0,115,109,111,111,116,104, 95,115,116,114,111,107,101, 95,114, 97,100,105,117,115, 0,115, +109,111,111,116,104, 95,115,116,114,111,107,101, 95,102, 97, 99,116,111,114, 0,114, 97,116,101, 0,114,103, 98, 91, 51, 93, 0, +115, 99,117,108,112,116, 95,112,108, 97,110,101, 0,112,108, 97,110,101, 95,111,102,102,115,101,116, 0,115, 99,117,108,112,116, + 95,116,111,111,108, 0,118,101,114,116,101,120,112, 97,105,110,116, 95,116,111,111,108, 0,105,109, 97,103,101,112, 97,105,110, +116, 95,116,111,111,108, 0,112, 97,100, 51, 91, 53, 93, 0, 97,117,116,111,115,109,111,111,116,104, 95,102, 97, 99,116,111,114, + 0, 99,114,101, 97,115,101, 95,112,105,110, 99,104, 95,102, 97, 99,116,111,114, 0,112,108, 97,110,101, 95,116,114,105,109, 0, +116,101,120,116,117,114,101, 95,115, 97,109,112,108,101, 95, 98,105, 97,115, 0,116,101,120,116,117,114,101, 95,111,118,101,114, +108, 97,121, 95, 97,108,112,104, 97, 0, 97,100,100, 95, 99,111,108, 91, 51, 93, 0,115,117, 98, 95, 99,111,108, 91, 51, 93, 0, + 97, 99,116,105,118,101, 95,114,110,100, 0, 97, 99,116,105,118,101, 95, 99,108,111,110,101, 0, 97, 99,116,105,118,101, 95,109, + 97,115,107, 0, 42,108, 97,121,101,114,115, 0,116,121,112,101,109, 97,112, 91, 51, 52, 93, 0,116,111,116,108, 97,121,101,114, + 0,109, 97,120,108, 97,121,101,114, 0,116,111,116,115,105,122,101, 0, 42,112,111,111,108, 0, 42,101,120,116,101,114,110, 97, +108, 0,114,111,116, 91, 52, 93, 0, 97,118,101, 91, 51, 93, 0, 42,103,114,111,117,110,100, 0,119, 97,110,100,101,114, 91, 51, + 93, 0,114,101,115,116, 95,108,101,110,103,116,104, 0,112, 97,114,116,105, 99,108,101, 95,105,110,100,101,120, 91, 50, 93, 0, +100,101,108,101,116,101, 95,102,108, 97,103, 0,110,117,109, 0,112, 97,114,101,110,116, 0,112, 97, 91, 52, 93, 0,119, 91, 52, + 93, 0,102,117,118, 91, 52, 93, 0,102,111,102,102,115,101,116, 0,112,114,101,118, 95,115,116, 97,116,101, 0, 42,104, 97,105, +114, 0, 42, 98,111,105,100, 0,100,105,101,116,105,109,101, 0,110,117,109, 95,100,109, 99, 97, 99,104,101, 0,104, 97,105,114, + 95,105,110,100,101,120, 0, 97,108,105,118,101, 0,115,112,114,105,110,103, 95,107, 0,112,108, 97,115,116,105, 99,105,116,121, + 95, 99,111,110,115,116, 97,110,116, 0,121,105,101,108,100, 95,114, 97,116,105,111, 0,112,108, 97,115,116,105, 99,105,116,121, + 95, 98, 97,108, 97,110, 99,101, 0,121,105,101,108,100, 95, 98, 97,108, 97,110, 99,101, 0,118,105,115, 99,111,115,105,116,121, + 95,111,109,101,103, 97, 0,118,105,115, 99,111,115,105,116,121, 95, 98,101,116, 97, 0,115,116,105,102,102,110,101,115,115, 95, +107, 0,115,116,105,102,102,110,101,115,115, 95,107,110,101, 97,114, 0,114,101,115,116, 95,100,101,110,115,105,116,121, 0, 98, +117,111,121, 97,110, 99,121, 0,115,112,114,105,110,103, 95,102,114, 97,109,101,115, 0, 42, 98,111,105,100,115, 0, 42,102,108, +117,105,100, 0,100,105,115,116,114, 0,112,104,121,115,116,121,112,101, 0, 97,118,101,109,111,100,101, 0,114,101, 97, 99,116, +101,118,101,110,116, 0,100,114, 97,119, 0,100,114, 97,119, 95, 97,115, 0,100,114, 97,119, 95,115,105,122,101, 0, 99,104,105, +108,100,116,121,112,101, 0,114,101,110, 95, 97,115, 0,115,117, 98,102,114, 97,109,101,115, 0,100,114, 97,119, 95, 99,111,108, + 0,114,101,110, 95,115,116,101,112, 0,104, 97,105,114, 95,115,116,101,112, 0,107,101,121,115, 95,115,116,101,112, 0, 97,100, + 97,112,116, 95, 97,110,103,108,101, 0, 97,100, 97,112,116, 95,112,105,120, 0,114,111,116,102,114,111,109, 0,105,110,116,101, +103,114, 97,116,111,114, 0, 98, 98, 95, 97,108,105,103,110, 0, 98, 98, 95,117,118, 95,115,112,108,105,116, 0, 98, 98, 95, 97, +110,105,109, 0, 98, 98, 95,115,112,108,105,116, 95,111,102,102,115,101,116, 0, 98, 98, 95,116,105,108,116, 0, 98, 98, 95,114, + 97,110,100, 95,116,105,108,116, 0, 98, 98, 95,111,102,102,115,101,116, 91, 50, 93, 0, 98, 98, 95,115,105,122,101, 91, 50, 93, + 0, 98, 98, 95,118,101,108, 95,104,101, 97,100, 0, 98, 98, 95,118,101,108, 95,116, 97,105,108, 0, 99,111,108,111,114, 95,118, +101, 99, 95,109, 97,120, 0,115,105,109,112,108,105,102,121, 95,114,101,102,115,105,122,101, 0,115,105,109,112,108,105,102,121, + 95,114, 97,116,101, 0,115,105,109,112,108,105,102,121, 95,116,114, 97,110,115,105,116,105,111,110, 0,115,105,109,112,108,105, +102,121, 95,118,105,101,119,112,111,114,116, 0,116,105,109,101,116,119,101, 97,107, 0, 99,111,117,114, 97,110,116, 95,116, 97, +114,103,101,116, 0,106,105,116,102, 97, 99, 0,101,102,102, 95,104, 97,105,114, 0,103,114,105,100, 95,114, 97,110,100, 0,112, +115, 95,111,102,102,115,101,116, 91, 49, 93, 0,103,114,105,100, 95,114,101,115, 0,101,102,102,101, 99,116,111,114, 95, 97,109, +111,117,110,116, 0,116,105,109,101, 95,102,108, 97,103, 0,116,105,109,101, 95,112, 97,100, 91, 51, 93, 0,112, 97,114,116,102, + 97, 99, 0,116, 97,110,102, 97, 99, 0,116, 97,110,112,104, 97,115,101, 0,114,101, 97, 99,116,102, 97, 99, 0,111, 98, 95,118, +101,108, 91, 51, 93, 0, 97,118,101,102, 97, 99, 0,112,104, 97,115,101,102, 97, 99, 0,114, 97,110,100,114,111,116,102, 97, 99, + 0,114, 97,110,100,112,104, 97,115,101,102, 97, 99, 0,114, 97,110,100,115,105,122,101, 0, 97, 99, 99, 91, 51, 93, 0,100,114, + 97,103,102, 97, 99, 0, 98,114,111,119,110,102, 97, 99, 0,114, 97,110,100,108,101,110,103,116,104, 0, 99,104,105,108,100, 95, +110, 98,114, 0,114,101,110, 95, 99,104,105,108,100, 95,110, 98,114, 0,112, 97,114,101,110,116,115, 0, 99,104,105,108,100,115, +105,122,101, 0, 99,104,105,108,100,114, 97,110,100,115,105,122,101, 0, 99,104,105,108,100,114, 97,100, 0, 99,104,105,108,100, +102,108, 97,116, 0, 99,108,117,109,112,112,111,119, 0,107,105,110,107, 95,102,108, 97,116, 0,107,105,110,107, 95, 97,109,112, + 95, 99,108,117,109,112, 0,114,111,117,103,104, 49, 0,114,111,117,103,104, 49, 95,115,105,122,101, 0,114,111,117,103,104, 50, + 0,114,111,117,103,104, 50, 95,115,105,122,101, 0,114,111,117,103,104, 50, 95,116,104,114,101,115, 0,114,111,117,103,104, 95, +101,110,100, 0,114,111,117,103,104, 95,101,110,100, 95,115,104, 97,112,101, 0, 99,108,101,110,103,116,104, 0, 99,108,101,110, +103,116,104, 95,116,104,114,101,115, 0,112, 97,114,116,105,110,103, 95,102, 97, 99, 0,112, 97,114,116,105,110,103, 95,109,105, +110, 0,112, 97,114,116,105,110,103, 95,109, 97,120, 0, 98,114, 97,110, 99,104, 95,116,104,114,101,115, 0,100,114, 97,119, 95, +108,105,110,101, 91, 50, 93, 0,112, 97,116,104, 95,115,116, 97,114,116, 0,112, 97,116,104, 95,101,110,100, 0,116,114, 97,105, +108, 95, 99,111,117,110,116, 0,107,101,121,101,100, 95,108,111,111,112,115, 0,100,117,112,108,105,119,101,105,103,104,116,115, + 0, 42,101,102,102, 95,103,114,111,117,112, 0, 42,100,117,112, 95,111, 98, 0, 42, 98, 98, 95,111, 98, 0, 42,112,100, 50, 0, + 42,112, 97,114,116, 0, 42,112, 97,114,116,105, 99,108,101,115, 0, 42, 42,112, 97,116,104, 99, 97, 99,104,101, 0, 42, 42, 99, +104,105,108,100, 99, 97, 99,104,101, 0,112, 97,116,104, 99, 97, 99,104,101, 98,117,102,115, 0, 99,104,105,108,100, 99, 97, 99, +104,101, 98,117,102,115, 0, 42, 99,108,109,100, 0, 42,104, 97,105,114, 95,105,110, 95,100,109, 0, 42,104, 97,105,114, 95,111, +117,116, 95,100,109, 0, 42,116, 97,114,103,101,116, 95,111, 98, 0, 42,108, 97,116,116,105, 99,101, 0,116,114,101,101, 95,102, +114, 97,109,101, 0, 98,118,104,116,114,101,101, 95,102,114, 97,109,101, 0, 99,104,105,108,100, 95,115,101,101,100, 0,116,111, +116,117,110,101,120,105,115,116, 0,116,111,116, 99,104,105,108,100, 0,116,111,116, 99, 97, 99,104,101,100, 0,116,111,116, 99, +104,105,108,100, 99, 97, 99,104,101, 0,116, 97,114,103,101,116, 95,112,115,121,115, 0,116,111,116,107,101,121,101,100, 0, 98, + 97,107,101,115,112, 97, 99,101, 0, 98, 98, 95,117,118,110, 97,109,101, 91, 51, 93, 91, 54, 52, 93, 0,118,103,114,111,117,112, + 91, 49, 50, 93, 0,118,103, 95,110,101,103, 0,114,116, 51, 0, 42,114,101,110,100,101,114,100, 97,116, 97, 0, 42,101,102,102, +101, 99,116,111,114,115, 0, 42,102,108,117,105,100, 95,115,112,114,105,110,103,115, 0,116,111,116, 95,102,108,117,105,100,115, +112,114,105,110,103,115, 0, 97,108,108,111, 99, 95,102,108,117,105,100,115,112,114,105,110,103,115, 0, 42,116,114,101,101, 0, + 42,112,100,100, 0, 42,102,114, 97,110,100, 0,100,116, 95,102,114, 97, 99, 0, 95,112, 97,100, 0, 67,100,105,115, 0, 67,118, +105, 0,115,116,114,117, 99,116,117,114, 97,108, 0, 98,101,110,100,105,110,103, 0,109, 97,120, 95, 98,101,110,100, 0,109, 97, +120, 95,115,116,114,117, 99,116, 0,109, 97,120, 95,115,104,101, 97,114, 0, 97,118,103, 95,115,112,114,105,110,103, 95,108,101, +110, 0,116,105,109,101,115, 99, 97,108,101, 0,101,102,102, 95,102,111,114, 99,101, 95,115, 99, 97,108,101, 0,101,102,102, 95, +119,105,110,100, 95,115, 99, 97,108,101, 0,115,105,109, 95,116,105,109,101, 95,111,108,100, 0,118,101,108,111, 99,105,116,121, + 95,115,109,111,111,116,104, 0, 99,111,108,108,105,100,101,114, 95,102,114,105, 99,116,105,111,110, 0,118,101,108, 95,100, 97, +109,112,105,110,103, 0,115,116,101,112,115, 80,101,114, 70,114, 97,109,101, 0,112,114,101,114,111,108,108, 0,109, 97,120,115, +112,114,105,110,103,108,101,110, 0,115,111,108,118,101,114, 95,116,121,112,101, 0,118,103,114,111,117,112, 95, 98,101,110,100, + 0,118,103,114,111,117,112, 95,109, 97,115,115, 0,118,103,114,111,117,112, 95,115,116,114,117, 99,116, 0,115,104, 97,112,101, +107,101,121, 95,114,101,115,116, 0,112,114,101,115,101,116,115, 0,114,101,115,101,116, 0, 42, 99,111,108,108,105,115,105,111, +110, 95,108,105,115,116, 0,101,112,115,105,108,111,110, 0,115,101,108,102, 95,102,114,105, 99,116,105,111,110, 0,115,101,108, +102,101,112,115,105,108,111,110, 0,114,101,112,101,108, 95,102,111,114, 99,101, 0,100,105,115,116, 97,110, 99,101, 95,114,101, +112,101,108, 0,115,101,108,102, 95,108,111,111,112, 95, 99,111,117,110,116, 0,108,111,111,112, 95, 99,111,117,110,116, 0,112, +114,101,115,115,117,114,101, 0,116,104,105, 99,107,110,101,115,115, 0,115,116,114,111,107,101,115, 0,102,114, 97,109,101,110, +117,109, 0, 42, 97, 99,116,102,114, 97,109,101, 0,103,115,116,101,112, 0,105,110,102,111, 91, 49, 50, 56, 93, 0,115, 98,117, +102,102,101,114, 95,115,105,122,101, 0,115, 98,117,102,102,101,114, 95,115,102,108, 97,103, 0, 42,115, 98,117,102,102,101,114, + 0,108,105,115,116, 0,112,114,105,110,116,108,101,118,101,108, 0,115,116,111,114,101,108,101,118,101,108, 0, 42,114,101,112, +111,114,116,116,105,109,101,114, 0, 42,119,105,110,100,114, 97,119, 97, 98,108,101, 0, 42,119,105,110, 97, 99,116,105,118,101, + 0,119,105,110,100,111,119,115, 0,105,110,105,116,105, 97,108,105,122,101,100, 0,102,105,108,101, 95,115, 97,118,101,100, 0, +111,112, 95,117,110,100,111, 95,100,101,112,116,104, 0,111,112,101,114, 97,116,111,114,115, 0,113,117,101,117,101, 0,114,101, +112,111,114,116,115, 0,106,111, 98,115, 0,112, 97,105,110,116, 99,117,114,115,111,114,115, 0,100,114, 97,103,115, 0,107,101, +121, 99,111,110,102,105,103,115, 0, 42,100,101,102, 97,117,108,116, 99,111,110,102, 0, 42, 97,100,100,111,110, 99,111,110,102, + 0, 42,117,115,101,114, 99,111,110,102, 0,116,105,109,101,114,115, 0, 42, 97,117,116,111,115, 97,118,101,116,105,109,101,114, + 0, 42,103,104,111,115,116,119,105,110, 0,103,114, 97, 98, 99,117,114,115,111,114, 0, 42,115, 99,114,101,101,110, 0, 42,110, +101,119,115, 99,114,101,101,110, 0,115, 99,114,101,101,110,110, 97,109,101, 91, 54, 52, 93, 0,112,111,115,120, 0,112,111,115, +121, 0,119,105,110,100,111,119,115,116, 97,116,101, 0,109,111,110,105,116,111,114, 0,108, 97,115,116, 99,117,114,115,111,114, + 0,109,111,100, 97,108, 99,117,114,115,111,114, 0, 97,100,100,109,111,117,115,101,109,111,118,101, 0, 42,101,118,101,110,116, +115,116, 97,116,101, 0, 42, 99,117,114,115,119,105,110, 0, 42,116,119,101, 97,107, 0,100,114, 97,119,109,101,116,104,111,100, + 0,100,114, 97,119,102, 97,105,108, 0, 42,100,114, 97,119,100, 97,116, 97, 0,109,111,100, 97,108,104, 97,110,100,108,101,114, +115, 0,115,117, 98,119,105,110,100,111,119,115, 0,103,101,115,116,117,114,101, 0,105,100,110, 97,109,101, 91, 54, 52, 93, 0, +112,114,111,112,118, 97,108,117,101, 0,115,104,105,102,116, 0, 99,116,114,108, 0, 97,108,116, 0,111,115,107,101,121, 0,107, +101,121,109,111,100,105,102,105,101,114, 0,109, 97,112,116,121,112,101, 0, 42,112,116,114, 0, 42,114,101,109,111,118,101, 95, +105,116,101,109, 0, 42, 97,100,100, 95,105,116,101,109, 0,105,116,101,109,115, 0,100,105,102,102, 95,105,116,101,109,115, 0, +115,112, 97, 99,101,105,100, 0,114,101,103,105,111,110,105,100, 0,107,109,105, 95,105,100, 0, 40, 42,112,111,108,108, 41, 40, + 41, 0, 42,109,111,100, 97,108, 95,105,116,101,109,115, 0, 98, 97,115,101,110, 97,109,101, 91, 54, 52, 93, 0, 97, 99,116,107, +101,121,109, 97,112, 0, 42, 99,117,115,116,111,109,100, 97,116, 97, 0, 42,112,121, 95,105,110,115,116, 97,110, 99,101, 0, 42, +114,101,112,111,114,116,115, 0,109, 97, 99,114,111, 0, 42,111,112,109, 0, 42,101,100, 97,116, 97, 0, 42, 99,111,101,102,102, +105, 99,105,101,110,116,115, 0, 97,114,114, 97,121,115,105,122,101, 0,112,111,108,121, 95,111,114,100,101,114, 0, 97,109,112, +108,105,116,117,100,101, 0,112,104, 97,115,101, 95,109,117,108,116,105,112,108,105,101,114, 0,112,104, 97,115,101, 95,111,102, +102,115,101,116, 0,118, 97,108,117,101, 95,111,102,102,115,101,116, 0,109,105,100,118, 97,108, 0, 98,101,102,111,114,101, 95, +109,111,100,101, 0, 97,102,116,101,114, 95,109,111,100,101, 0, 98,101,102,111,114,101, 95, 99,121, 99,108,101,115, 0, 97,102, +116,101,114, 95, 99,121, 99,108,101,115, 0,114,101, 99,116, 0,112,104, 97,115,101, 0,109,111,100,105,102,105, 99, 97,116,105, +111,110, 0,115,116,101,112, 95,115,105,122,101, 0, 42,114,110, 97, 95,112, 97,116,104, 0,112, 99,104, 97,110, 95,110, 97,109, +101, 91, 51, 50, 93, 0,116,114, 97,110,115, 67,104, 97,110, 0,105,100,116,121,112,101, 0,116, 97,114,103,101,116,115, 91, 56, + 93, 0,110,117,109, 95,116, 97,114,103,101,116,115, 0,118, 97,114,105, 97, 98,108,101,115, 0,101,120,112,114,101,115,115,105, +111,110, 91, 50, 53, 54, 93, 0, 42,101,120,112,114, 95, 99,111,109,112, 0,118,101, 99, 91, 50, 93, 0, 42,102,112,116, 0, 97, +114,114, 97,121, 95,105,110,100,101,120, 0, 99,111,108,111,114, 95,109,111,100,101, 0, 99,111,108,111,114, 91, 51, 93, 0,102, +114,111,109, 91, 49, 50, 56, 93, 0,116,111, 91, 49, 50, 56, 93, 0,109, 97,112,112,105,110,103,115, 0,115,116,114,105,112,115, + 0, 42,114,101,109, 97,112, 0,102, 99,117,114,118,101,115, 0,115,116,114,105,112, 95,116,105,109,101, 0, 98,108,101,110,100, +109,111,100,101, 0,101,120,116,101,110,100,109,111,100,101, 0, 42,115,112,101, 97,107,101,114, 95,104, 97,110,100,108,101, 0, +103,114,111,117,112, 91, 54, 52, 93, 0,103,114,111,117,112,109,111,100,101, 0,107,101,121,105,110,103,102,108, 97,103, 0,112, + 97,116,104,115, 0,100,101,115, 99,114,105,112,116,105,111,110, 91, 50, 52, 48, 93, 0,116,121,112,101,105,110,102,111, 91, 54, + 52, 93, 0, 97, 99,116,105,118,101, 95,112, 97,116,104, 0, 42,116,109,112, 97, 99,116, 0,110,108, 97, 95,116,114, 97, 99,107, +115, 0, 42, 97, 99,116,115,116,114,105,112, 0,100,114,105,118,101,114,115, 0,111,118,101,114,114,105,100,101,115, 0, 97, 99, +116, 95, 98,108,101,110,100,109,111,100,101, 0, 97, 99,116, 95,101,120,116,101,110,100,109,111,100,101, 0, 97, 99,116, 95,105, +110,102,108,117,101,110, 99,101, 0,114,117,108,101, 0,111,112,116,105,111,110,115, 0,102,101, 97,114, 95,102, 97, 99,116,111, +114, 0,115,105,103,110, 97,108, 95,105,100, 0,108,111,111,107, 95, 97,104,101, 97,100, 0,111,108,111, 99, 91, 51, 93, 0,113, +117,101,117,101, 95,115,105,122,101, 0,119, 97,110,100,101,114, 0,102,108,101,101, 95,100,105,115,116, 97,110, 99,101, 0,104, +101, 97,108,116,104, 0,115,116, 97,116,101, 95,105,100, 0,114,117,108,101,115, 0, 99,111,110,100,105,116,105,111,110,115, 0, + 97, 99,116,105,111,110,115, 0,114,117,108,101,115,101,116, 95,116,121,112,101, 0,114,117,108,101, 95,102,117,122,122,105,110, +101,115,115, 0,108, 97,115,116, 95,115,116, 97,116,101, 95,105,100, 0,108, 97,110,100,105,110,103, 95,115,109,111,111,116,104, +110,101,115,115, 0, 98, 97,110,107,105,110,103, 0, 97,103,103,114,101,115,115,105,111,110, 0, 97,105,114, 95,109,105,110, 95, +115,112,101,101,100, 0, 97,105,114, 95,109, 97,120, 95,115,112,101,101,100, 0, 97,105,114, 95,109, 97,120, 95, 97, 99, 99, 0, + 97,105,114, 95,109, 97,120, 95, 97,118,101, 0, 97,105,114, 95,112,101,114,115,111,110, 97,108, 95,115,112, 97, 99,101, 0,108, + 97,110,100, 95,106,117,109,112, 95,115,112,101,101,100, 0,108, 97,110,100, 95,109, 97,120, 95,115,112,101,101,100, 0,108, 97, +110,100, 95,109, 97,120, 95, 97, 99, 99, 0,108, 97,110,100, 95,109, 97,120, 95, 97,118,101, 0,108, 97,110,100, 95,112,101,114, +115,111,110, 97,108, 95,115,112, 97, 99,101, 0,108, 97,110,100, 95,115,116,105, 99,107, 95,102,111,114, 99,101, 0,115,116, 97, +116,101,115, 0, 42,115,109,100, 0, 42,102,108,117,105,100, 95,103,114,111,117,112, 0, 42, 99,111,108,108, 95,103,114,111,117, +112, 0, 42,119,116, 0, 42,116,101,120, 95,119,116, 0, 42,116,101,120, 95,115,104, 97,100,111,119, 0, 42,115,104, 97,100,111, +119, 0,112, 48, 91, 51, 93, 0,112, 49, 91, 51, 93, 0,100,120, 0,111,109,101,103, 97, 0,116,101,109,112, 65,109, 98, 0, 98, +101,116, 97, 0,114,101,115, 91, 51, 93, 0, 97,109,112,108,105,102,121, 0,109, 97,120,114,101,115, 0,118,105,101,119,115,101, +116,116,105,110,103,115, 0,110,111,105,115,101, 0,100,105,115,115, 95,112,101,114, 99,101,110,116, 0,100,105,115,115, 95,115, +112,101,101,100, 0,114,101,115, 95,119,116, 91, 51, 93, 0,100,120, 95,119,116, 0,118, 51,100,110,117,109, 0, 99, 97, 99,104, +101, 95, 99,111,109,112, 0, 99, 97, 99,104,101, 95,104,105,103,104, 95, 99,111,109,112, 0, 42,112,111,105,110,116, 95, 99, 97, + 99,104,101, 91, 50, 93, 0,112,116, 99, 97, 99,104,101,115, 91, 50, 93, 0, 98,111,114,100,101,114, 95, 99,111,108,108,105,115, +105,111,110,115, 0,116,105,109,101, 95,115, 99, 97,108,101, 0,118,111,114,116,105, 99,105,116,121, 0,118,101,108,111, 99,105, +116,121, 91, 50, 93, 0,118,101,108, 95,109,117,108,116,105, 0,118,103,114,112, 95,104,101, 97,116, 95,115, 99, 97,108,101, 91, + 50, 93, 0,118,103,114,111,117,112, 95,102,108,111,119, 0,118,103,114,111,117,112, 95,100,101,110,115,105,116,121, 0,118,103, +114,111,117,112, 95,104,101, 97,116, 0, 42,112,111,105,110,116,115, 95,111,108,100, 0, 42,118,101,108, 0,109, 97,116, 95,111, +108,100, 91, 52, 93, 91, 52, 93, 0,118,111,108,117,109,101, 95,109, 97,120, 0,118,111,108,117,109,101, 95,109,105,110, 0,100, +105,115,116, 97,110, 99,101, 95,109, 97,120, 0,100,105,115,116, 97,110, 99,101, 95,114,101,102,101,114,101,110, 99,101, 0, 99, +111,110,101, 95, 97,110,103,108,101, 95,111,117,116,101,114, 0, 99,111,110,101, 95, 97,110,103,108,101, 95,105,110,110,101,114, + 0, 99,111,110,101, 95,118,111,108,117,109,101, 95,111,117,116,101,114, 0,114,101,110,100,101,114, 95,102,108, 97,103, 0, 98, +117,105,108,100, 95,115,105,122,101, 95,102,108, 97,103, 0, 98,117,105,108,100, 95,116, 99, 95,102,108, 97,103, 0,108, 97,115, +116,115,105,122,101, 91, 50, 93, 0,116,114, 97, 99,107,105,110,103, 0, 42,116,114, 97, 99,107,105,110,103, 95, 99,111,110,116, +101,120,116, 0,112,114,111,120,121, 0,116,114, 97, 99,107, 95,112,114,101,118,105,101,119, 95,104,101,105,103,104,116, 0, 42, +116,114, 97, 99,107, 95,112,114,101,118,105,101,119, 0,116,114, 97, 99,107, 95,112,111,115, 91, 50, 93, 0,116,114, 97, 99,107, + 95,100,105,115, 97, 98,108,101,100, 0, 42,109, 97,114,107,101,114, 0,115,108,105,100,101, 95,115, 99, 97,108,101, 91, 50, 93, + 0,101,114,114,111,114, 0, 42,105,110,116,114,105,110,115,105, 99,115, 0,115,101,110,115,111,114, 95,119,105,100,116,104, 0, +112,105,120,101,108, 95, 97,115,112,101, 99,116, 0,102,111, 99, 97,108, 0,117,110,105,116,115, 0,112,114,105,110, 99,105,112, + 97,108, 91, 50, 93, 0,107, 49, 0,107, 50, 0,107, 51, 0,112,111,115, 91, 50, 93, 0,112, 97,116, 95,109,105,110, 91, 50, 93, + 0,112, 97,116, 95,109, 97,120, 91, 50, 93, 0,115,101, 97,114, 99,104, 95,109,105,110, 91, 50, 93, 0,115,101, 97,114, 99,104, + 95,109, 97,120, 91, 50, 93, 0,109, 97,114,107,101,114,115,110,114, 0,108, 97,115,116, 95,109, 97,114,107,101,114, 0, 42,109, + 97,114,107,101,114,115, 0, 98,117,110,100,108,101, 95,112,111,115, 91, 51, 93, 0,112, 97,116, 95,102,108, 97,103, 0,115,101, + 97,114, 99,104, 95,102,108, 97,103, 0,102,114, 97,109,101,115, 95,108,105,109,105,116, 0,112, 97,116,116,101,114,110, 95,109, + 97,116, 99,104, 0,116,114, 97, 99,107,101,114, 0,112,121,114, 97,109,105,100, 95,108,101,118,101,108,115, 0,109,105,110,105, +109,117,109, 95, 99,111,114,114,101,108, 97,116,105,111,110, 0,100,101,102, 97,117,108,116, 95,116,114, 97, 99,107,101,114, 0, +100,101,102, 97,117,108,116, 95,112,121,114, 97,109,105,100, 95,108,101,118,101,108,115, 0,100,101,102, 97,117,108,116, 95,109, +105,110,105,109,117,109, 95, 99,111,114,114,101,108, 97,116,105,111,110, 0,100,101,102, 97,117,108,116, 95,112, 97,116,116,101, +114,110, 95,115,105,122,101, 0,100,101,102, 97,117,108,116, 95,115,101, 97,114, 99,104, 95,115,105,122,101, 0,100,101,102, 97, +117,108,116, 95,102,114, 97,109,101,115, 95,108,105,109,105,116, 0,100,101,102, 97,117,108,116, 95,109, 97,114,103,105,110, 0, +100,101,102, 97,117,108,116, 95,112, 97,116,116,101,114,110, 95,109, 97,116, 99,104, 0,100,101,102, 97,117,108,116, 95,102,108, + 97,103, 0,109,111,116,105,111,110, 95,102,108, 97,103, 0,107,101,121,102,114, 97,109,101, 49, 0,107,101,121,102,114, 97,109, +101, 50, 0,114,101,102,105,110,101, 95, 99, 97,109,101,114, 97, 95,105,110,116,114,105,110,115,105, 99,115, 0, 99,108,101, 97, +110, 95,102,114, 97,109,101,115, 0, 99,108,101, 97,110, 95, 97, 99,116,105,111,110, 0, 99,108,101, 97,110, 95,101,114,114,111, +114, 0,111, 98,106,101, 99,116, 95,100,105,115,116, 97,110, 99,101, 0,116,111,116, 95,116,114, 97, 99,107, 0, 97, 99,116, 95, +116,114, 97, 99,107, 0,109, 97,120,115, 99, 97,108,101, 0, 42,114,111,116, 95,116,114, 97, 99,107, 0,108,111, 99,105,110,102, + 0,115, 99, 97,108,101,105,110,102, 0,114,111,116,105,110,102, 0, 42,115, 99, 97,108,101,105, 98,117,102, 0,108, 97,115,116, + 95, 99, 97,109,101,114, 97, 0, 99, 97,109,110,114, 0, 42, 99, 97,109,101,114, 97,115, 0,116,114, 97, 99,107,115, 0,114,101, + 99,111,110,115,116,114,117, 99,116,105,111,110, 0,109,101,115,115, 97,103,101, 91, 50, 53, 54, 93, 0,115,101,116,116,105,110, +103,115, 0, 99, 97,109,101,114, 97, 0,115,116, 97, 98,105,108,105,122, 97,116,105,111,110, 0, 42, 97, 99,116, 95,116,114, 97, + 99,107, 0,111, 98,106,101, 99,116,115, 0,111, 98,106,101, 99,116,110,114, 0,116,111,116, 95,111, 98,106,101, 99,116, 0, 42, + 98,114,117,115,104, 95,103,114,111,117,112, 0, 99,117,114,114,101,110,116, 95,102,114, 97,109,101, 0,100,105,115,112, 95,116, +121,112,101, 0,105,109, 97,103,101, 95,102,105,108,101,102,111,114,109, 97,116, 0,101,102,102,101, 99,116, 95,117,105, 0,112, +114,101,118,105,101,119, 95,105,100, 0,105,110,105,116, 95, 99,111,108,111,114, 95,116,121,112,101, 0,112, 97,100, 95,115, 0, +105,109, 97,103,101, 95,114,101,115,111,108,117,116,105,111,110, 0,115,117, 98,115,116,101,112,115, 0,105,110,105,116, 95, 99, +111,108,111,114, 91, 52, 93, 0, 42,105,110,105,116, 95,116,101,120,116,117,114,101, 0,105,110,105,116, 95,108, 97,121,101,114, +110, 97,109,101, 91, 54, 52, 93, 0,100,114,121, 95,115,112,101,101,100, 0, 99,111,108,111,114, 95,100,114,121, 95,116,104,114, +101,115,104,111,108,100, 0,100,101,112,116,104, 95, 99,108, 97,109,112, 0,100,105,115,112, 95,102, 97, 99,116,111,114, 0,115, +112,114,101, 97,100, 95,115,112,101,101,100, 0, 99,111,108,111,114, 95,115,112,114,101, 97,100, 95,115,112,101,101,100, 0,115, +104,114,105,110,107, 95,115,112,101,101,100, 0,100,114,105,112, 95,118,101,108, 0,100,114,105,112, 95, 97, 99, 99, 0,105,110, +102,108,117,101,110, 99,101, 95,115, 99, 97,108,101, 0,114, 97,100,105,117,115, 95,115, 99, 97,108,101, 0,119, 97,118,101, 95, +100, 97,109,112,105,110,103, 0,119, 97,118,101, 95,115,112,101,101,100, 0,119, 97,118,101, 95,116,105,109,101,115, 99, 97,108, +101, 0,119, 97,118,101, 95,115,112,114,105,110,103, 0,105,109, 97,103,101, 95,111,117,116,112,117,116, 95,112, 97,116,104, 91, + 49, 48, 50, 52, 93, 0,111,117,116,112,117,116, 95,110, 97,109,101, 91, 54, 52, 93, 0,111,117,116,112,117,116, 95,110, 97,109, +101, 50, 91, 54, 52, 93, 0, 42,112,109,100, 0,115,117,114,102, 97, 99,101,115, 0, 97, 99,116,105,118,101, 95,115,117,114, 0, +101,114,114,111,114, 91, 54, 52, 93, 0, 99,111,108,108,105,115,105,111,110, 0,119,101,116,110,101,115,115, 0,112, 97,114,116, +105, 99,108,101, 95,114, 97,100,105,117,115, 0,112, 97,114,116,105, 99,108,101, 95,115,109,111,111,116,104, 0,112, 97,105,110, +116, 95,100,105,115,116, 97,110, 99,101, 0, 42,112, 97,105,110,116, 95,114, 97,109,112, 0, 42,118,101,108, 95,114, 97,109,112, + 0,112,114,111,120,105,109,105,116,121, 95,102, 97,108,108,111,102,102, 0,114, 97,121, 95,100,105,114, 0,119, 97,118,101, 95, +102, 97, 99,116,111,114, 0,119, 97,118,101, 95, 99,108, 97,109,112, 0,109, 97,120, 95,118,101,108,111, 99,105,116,121, 0,115, +109,117,100,103,101, 95,115,116,114,101,110,103,116,104, 0, 0, 84, 89, 80, 69, 16, 2, 0, 0, 99,104, 97,114, 0,117, 99,104, + 97,114, 0,115,104,111,114,116, 0,117,115,104,111,114,116, 0,105,110,116, 0,108,111,110,103, 0,117,108,111,110,103, 0,102, +108,111, 97,116, 0,100,111,117, 98,108,101, 0,105,110,116, 54, 52, 95,116, 0,117,105,110,116, 54, 52, 95,116, 0,118,111,105, +100, 0, 76,105,110,107, 0, 76,105,110,107, 68, 97,116, 97, 0, 76,105,115,116, 66, 97,115,101, 0,118,101, 99, 50,115, 0,118, +101, 99, 50,102, 0,118,101, 99, 51,102, 0,114, 99,116,105, 0,114, 99,116,102, 0, 73, 68, 80,114,111,112,101,114,116,121, 68, + 97,116, 97, 0, 73, 68, 80,114,111,112,101,114,116,121, 0, 73, 68, 0, 76,105, 98,114, 97,114,121, 0, 70,105,108,101, 68, 97, +116, 97, 0, 80,114,101,118,105,101,119, 73,109, 97,103,101, 0, 73,112,111, 68,114,105,118,101,114, 0, 79, 98,106,101, 99,116, + 0, 73,112,111, 67,117,114,118,101, 0, 66, 80,111,105,110,116, 0, 66,101,122, 84,114,105,112,108,101, 0, 73,112,111, 0, 75, +101,121, 66,108,111, 99,107, 0, 75,101,121, 0, 65,110,105,109, 68, 97,116, 97, 0, 84,101,120,116, 76,105,110,101, 0, 84,101, +120,116, 77, 97,114,107,101,114, 0, 84,101,120,116, 0, 80, 97, 99,107,101,100, 70,105,108,101, 0, 67, 97,109,101,114, 97, 0, + 73,109, 97,103,101, 85,115,101,114, 0, 83, 99,101,110,101, 0, 73,109, 97,103,101, 0, 71, 80, 85, 84,101,120,116,117,114,101, + 0, 97,110,105,109, 0, 82,101,110,100,101,114, 82,101,115,117,108,116, 0, 77, 84,101,120, 0, 84,101,120, 0, 80,108,117,103, +105,110, 84,101,120, 0, 67, 66, 68, 97,116, 97, 0, 67,111,108,111,114, 66, 97,110,100, 0, 69,110,118, 77, 97,112, 0, 73,109, + 66,117,102, 0, 80,111,105,110,116, 68,101,110,115,105,116,121, 0, 67,117,114,118,101, 77, 97,112,112,105,110,103, 0, 86,111, +120,101,108, 68, 97,116, 97, 0, 79, 99,101, 97,110, 84,101,120, 0, 98, 78,111,100,101, 84,114,101,101, 0, 84,101,120, 77, 97, +112,112,105,110,103, 0, 67,111,108,111,114, 77, 97,112,112,105,110,103, 0, 76, 97,109,112, 0, 86,111,108,117,109,101, 83,101, +116,116,105,110,103,115, 0, 71, 97,109,101, 83,101,116,116,105,110,103,115, 0, 77, 97,116,101,114,105, 97,108, 0, 71,114,111, +117,112, 0, 86, 70,111,110,116, 0, 86, 70,111,110,116, 68, 97,116, 97, 0, 77,101,116, 97, 69,108,101,109, 0, 66,111,117,110, +100, 66,111,120, 0, 77,101,116, 97, 66, 97,108,108, 0, 78,117,114, 98, 0, 67,104, 97,114, 73,110,102,111, 0, 84,101,120,116, + 66,111,120, 0, 69,100,105,116, 78,117,114, 98, 0, 71, 72, 97,115,104, 0, 67,117,114,118,101, 0, 80, 97,116,104, 0, 83,101, +108, 66,111,120, 0, 69,100,105,116, 70,111,110,116, 0, 77,101,115,104, 0, 77, 83,101,108,101, 99,116, 0, 77, 80,111,108,121, + 0, 77, 84,101,120, 80,111,108,121, 0, 77, 76,111,111,112, 0, 77, 76,111,111,112, 85, 86, 0, 77, 76,111,111,112, 67,111,108, + 0, 77, 70, 97, 99,101, 0, 77, 84, 70, 97, 99,101, 0, 84, 70, 97, 99,101, 0, 77, 86,101,114,116, 0, 77, 69,100,103,101, 0, + 77, 68,101,102,111,114,109, 86,101,114,116, 0, 77, 67,111,108, 0, 77, 83,116,105, 99,107,121, 0, 66, 77, 69,100,105,116, 77, +101,115,104, 0, 67,117,115,116,111,109, 68, 97,116, 97, 0, 77,117,108,116,105,114,101,115, 0, 77, 68,101,102,111,114,109, 87, +101,105,103,104,116, 0, 77, 70,108,111, 97,116, 80,114,111,112,101,114,116,121, 0, 77, 73,110,116, 80,114,111,112,101,114,116, +121, 0, 77, 83,116,114,105,110,103, 80,114,111,112,101,114,116,121, 0, 79,114,105,103, 83,112, 97, 99,101, 70, 97, 99,101, 0, + 79,114,105,103, 83,112, 97, 99,101, 76,111,111,112, 0, 77, 68,105,115,112,115, 0, 77,117,108,116,105,114,101,115, 67,111,108, + 0, 77,117,108,116,105,114,101,115, 67,111,108, 70, 97, 99,101, 0, 77,117,108,116,105,114,101,115, 70, 97, 99,101, 0, 77,117, +108,116,105,114,101,115, 69,100,103,101, 0, 77,117,108,116,105,114,101,115, 76,101,118,101,108, 0, 77, 82,101, 99, 97,115,116, + 0, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77, 97,112,112,105,110,103, 73,110,102,111, 77,111,100,105,102,105,101, +114, 68, 97,116, 97, 0, 83,117, 98,115,117,114,102, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 76, 97,116,116,105, 99, +101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67,117,114,118,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, + 66,117,105,108,100, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77, 97,115,107, 77,111,100,105,102,105,101,114, 68, 97, +116, 97, 0, 65,114,114, 97,121, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77,105,114,114,111,114, 77,111,100,105,102, +105,101,114, 68, 97,116, 97, 0, 69,100,103,101, 83,112,108,105,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 66,101, +118,101,108, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 66, 77,101,115,104, 77,111,100,105,102,105,101,114, 68, 97,116, + 97, 0, 83,109,111,107,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,109,111,107,101, 68,111,109, 97,105,110, 83, +101,116,116,105,110,103,115, 0, 83,109,111,107,101, 70,108,111,119, 83,101,116,116,105,110,103,115, 0, 83,109,111,107,101, 67, +111,108,108, 83,101,116,116,105,110,103,115, 0, 68,105,115,112,108, 97, 99,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, + 0, 85, 86, 80,114,111,106,101, 99,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 68,101, 99,105,109, 97,116,101, 77, +111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,109,111,111,116,104, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67, + 97,115,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 87, 97,118,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, + 0, 65,114,109, 97,116,117,114,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 72,111,111,107, 77,111,100,105,102,105, +101,114, 68, 97,116, 97, 0, 83,111,102,116, 98,111,100,121, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67,108,111,116, +104, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67,108,111,116,104, 0, 67,108,111,116,104, 83,105,109, 83,101,116,116, +105,110,103,115, 0, 67,108,111,116,104, 67,111,108,108, 83,101,116,116,105,110,103,115, 0, 80,111,105,110,116, 67, 97, 99,104, +101, 0, 67,111,108,108,105,115,105,111,110, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 66, 86, 72, 84,114,101,101, 0, + 83,117,114,102, 97, 99,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 68,101,114,105,118,101,100, 77,101,115,104, 0, + 66, 86, 72, 84,114,101,101, 70,114,111,109, 77,101,115,104, 0, 66,111,111,108,101, 97,110, 77,111,100,105,102,105,101,114, 68, + 97,116, 97, 0, 77, 68,101,102, 73,110,102,108,117,101,110, 99,101, 0, 77, 68,101,102, 67,101,108,108, 0, 77,101,115,104, 68, +101,102,111,114,109, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108,101, 83,121,115,116,101,109, + 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108,101, 83,121,115,116,101,109, 0, 80, 97,114,116, +105, 99,108,101, 73,110,115,116, 97,110, 99,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 69,120,112,108,111,100,101, + 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77,117,108,116,105,114,101,115, 77,111,100,105,102,105,101,114, 68, 97,116, + 97, 0, 70,108,117,105,100,115,105,109, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 70,108,117,105,100,115,105,109, 83, +101,116,116,105,110,103,115, 0, 83,104,114,105,110,107,119,114, 97,112, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83, +105,109,112,108,101, 68,101,102,111,114,109, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,104, 97,112,101, 75,101,121, + 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,111,108,105,100,105,102,121, 77,111,100,105,102,105,101,114, 68, 97,116, + 97, 0, 83, 99,114,101,119, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 79, 99,101, 97,110, 77,111,100,105,102,105,101, +114, 68, 97,116, 97, 0, 79, 99,101, 97,110, 0, 79, 99,101, 97,110, 67, 97, 99,104,101, 0, 87, 97,114,112, 77,111,100,105,102, +105,101,114, 68, 97,116, 97, 0, 87,101,105,103,104,116, 86, 71, 69,100,105,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, + 0, 87,101,105,103,104,116, 86, 71, 77,105,120, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 87,101,105,103,104,116, 86, + 71, 80,114,111,120,105,109,105,116,121, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 68,121,110, 97,109,105, 99, 80, 97, +105,110,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 68,121,110, 97,109,105, 99, 80, 97,105,110,116, 67, 97,110,118, + 97,115, 83,101,116,116,105,110,103,115, 0, 68,121,110, 97,109,105, 99, 80, 97,105,110,116, 66,114,117,115,104, 83,101,116,116, +105,110,103,115, 0, 82,101,109,101,115,104, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 69,100,105,116, 76, 97,116,116, + 0, 76, 97,116,116,105, 99,101, 0, 98, 68,101,102,111,114,109, 71,114,111,117,112, 0, 83, 99,117,108,112,116, 83,101,115,115, +105,111,110, 0, 98, 65, 99,116,105,111,110, 0, 98, 80,111,115,101, 0, 98, 71, 80,100, 97,116, 97, 0, 98, 65,110,105,109, 86, +105,122, 83,101,116,116,105,110,103,115, 0, 98, 77,111,116,105,111,110, 80, 97,116,104, 0, 66,117,108,108,101,116, 83,111,102, +116, 66,111,100,121, 0, 80, 97,114,116, 68,101,102,108,101, 99,116, 0, 83,111,102,116, 66,111,100,121, 0, 79, 98, 72,111,111, +107, 0, 68,117,112,108,105, 79, 98,106,101, 99,116, 0, 82, 78, 71, 0, 69,102,102,101, 99,116,111,114, 87,101,105,103,104,116, +115, 0, 80, 84, 67, 97, 99,104,101, 69,120,116,114, 97, 0, 80, 84, 67, 97, 99,104,101, 77,101,109, 0, 80, 84, 67, 97, 99,104, +101, 69,100,105,116, 0, 83, 66, 86,101,114,116,101,120, 0, 66,111,100,121, 80,111,105,110,116, 0, 66,111,100,121, 83,112,114, +105,110,103, 0, 83, 66, 83, 99,114, 97,116, 99,104, 0, 70,108,117,105,100, 86,101,114,116,101,120, 86,101,108,111, 99,105,116, +121, 0, 87,111,114,108,100, 0, 66, 97,115,101, 0, 65,118,105, 67,111,100,101, 99, 68, 97,116, 97, 0, 81,117,105, 99,107,116, +105,109,101, 67,111,100,101, 99, 68, 97,116, 97, 0, 81,117,105, 99,107,116,105,109,101, 67,111,100,101, 99, 83,101,116,116,105, +110,103,115, 0, 70, 70, 77,112,101,103, 67,111,100,101, 99, 68, 97,116, 97, 0, 65,117,100,105,111, 68, 97,116, 97, 0, 83, 99, +101,110,101, 82,101,110,100,101,114, 76, 97,121,101,114, 0, 73,109, 97,103,101, 70,111,114,109, 97,116, 68, 97,116, 97, 0, 82, +101,110,100,101,114, 68, 97,116, 97, 0, 82,101,110,100,101,114, 80,114,111,102,105,108,101, 0, 71, 97,109,101, 68,111,109,101, + 0, 71, 97,109,101, 70,114, 97,109,105,110,103, 0, 82,101, 99, 97,115,116, 68, 97,116, 97, 0, 71, 97,109,101, 68, 97,116, 97, + 0, 84,105,109,101, 77, 97,114,107,101,114, 0, 80, 97,105,110,116, 0, 66,114,117,115,104, 0, 73,109, 97,103,101, 80, 97,105, +110,116, 83,101,116,116,105,110,103,115, 0, 80, 97,114,116,105, 99,108,101, 66,114,117,115,104, 68, 97,116, 97, 0, 80, 97,114, +116,105, 99,108,101, 69,100,105,116, 83,101,116,116,105,110,103,115, 0, 83, 99,117,108,112,116, 0, 85,118, 83, 99,117,108,112, +116, 0, 86, 80, 97,105,110,116, 0, 84,114, 97,110,115,102,111,114,109, 79,114,105,101,110,116, 97,116,105,111,110, 0, 85,110, +105,102,105,101,100, 80, 97,105,110,116, 83,101,116,116,105,110,103,115, 0, 84,111,111,108, 83,101,116,116,105,110,103,115, 0, + 98, 83,116, 97,116,115, 0, 85,110,105,116, 83,101,116,116,105,110,103,115, 0, 80,104,121,115,105, 99,115, 83,101,116,116,105, +110,103,115, 0, 69,100,105,116,105,110,103, 0, 83, 99,101,110,101, 83,116, 97,116,115, 0, 68, 97,103, 70,111,114,101,115,116, + 0, 77,111,118,105,101, 67,108,105,112, 0, 66, 71,112,105, 99, 0, 77,111,118,105,101, 67,108,105,112, 85,115,101,114, 0, 82, +101,103,105,111,110, 86,105,101,119, 51, 68, 0, 82,101,110,100,101,114, 73,110,102,111, 0, 82,101,110,100,101,114, 69,110,103, +105,110,101, 0, 86,105,101,119, 68,101,112,116,104,115, 0, 83,109,111,111,116,104, 86,105,101,119, 83,116,111,114,101, 0,119, +109, 84,105,109,101,114, 0, 86,105,101,119, 51, 68, 0, 83,112, 97, 99,101, 76,105,110,107, 0, 86,105,101,119, 50, 68, 0, 83, +112, 97, 99,101, 73,110,102,111, 0, 83,112, 97, 99,101, 73,112,111, 0, 98, 68,111,112,101, 83,104,101,101,116, 0, 83,112, 97, + 99,101, 66,117,116,115, 0, 83,112, 97, 99,101, 83,101,113, 0, 70,105,108,101, 83,101,108,101, 99,116, 80, 97,114, 97,109,115, + 0, 83,112, 97, 99,101, 70,105,108,101, 0, 70,105,108,101, 76,105,115,116, 0,119,109, 79,112,101,114, 97,116,111,114, 0, 70, +105,108,101, 76, 97,121,111,117,116, 0, 83,112, 97, 99,101, 79,111,112,115, 0, 84,114,101,101, 83,116,111,114,101, 0, 84,114, +101,101, 83,116,111,114,101, 69,108,101,109, 0, 83,112, 97, 99,101, 73,109, 97,103,101, 0, 83, 99,111,112,101,115, 0, 72,105, +115,116,111,103,114, 97,109, 0, 83,112, 97, 99,101, 78,108, 97, 0, 83,112, 97, 99,101, 84,101,120,116, 0, 83, 99,114,105,112, +116, 0, 83,112, 97, 99,101, 83, 99,114,105,112,116, 0, 83,112, 97, 99,101, 84,105,109,101, 67, 97, 99,104,101, 0, 83,112, 97, + 99,101, 84,105,109,101, 0, 83,112, 97, 99,101, 78,111,100,101, 0, 83,112, 97, 99,101, 76,111,103,105, 99, 0, 67,111,110,115, +111,108,101, 76,105,110,101, 0, 83,112, 97, 99,101, 67,111,110,115,111,108,101, 0, 83,112, 97, 99,101, 85,115,101,114, 80,114, +101,102, 0, 83,112, 97, 99,101, 67,108,105,112, 0, 77,111,118,105,101, 67,108,105,112, 83, 99,111,112,101,115, 0,117,105, 70, +111,110,116, 0,117,105, 70,111,110,116, 83,116,121,108,101, 0,117,105, 83,116,121,108,101, 0,117,105, 87,105,100,103,101,116, + 67,111,108,111,114,115, 0,117,105, 87,105,100,103,101,116, 83,116, 97,116,101, 67,111,108,111,114,115, 0,117,105, 80, 97,110, +101,108, 67,111,108,111,114,115, 0, 84,104,101,109,101, 85, 73, 0, 84,104,101,109,101, 83,112, 97, 99,101, 0, 84,104,101,109, +101, 87,105,114,101, 67,111,108,111,114, 0, 98, 84,104,101,109,101, 0, 98, 65,100,100,111,110, 0, 83,111,108,105,100, 76,105, +103,104,116, 0, 85,115,101,114, 68,101,102, 0, 98, 83, 99,114,101,101,110, 0, 83, 99,114, 86,101,114,116, 0, 83, 99,114, 69, +100,103,101, 0, 80, 97,110,101,108, 0, 80, 97,110,101,108, 84,121,112,101, 0,117,105, 76, 97,121,111,117,116, 0, 83, 99,114, + 65,114,101, 97, 0, 83,112, 97, 99,101, 84,121,112,101, 0, 65, 82,101,103,105,111,110, 0, 65, 82,101,103,105,111,110, 84,121, +112,101, 0, 70,105,108,101, 71,108,111, 98, 97,108, 0, 83,116,114,105,112, 69,108,101,109, 0, 83,116,114,105,112, 67,114,111, +112, 0, 83,116,114,105,112, 84,114, 97,110,115,102,111,114,109, 0, 83,116,114,105,112, 67,111,108,111,114, 66, 97,108, 97,110, + 99,101, 0, 83,116,114,105,112, 80,114,111,120,121, 0, 83,116,114,105,112, 0, 80,108,117,103,105,110, 83,101,113, 0, 83,101, +113,117,101,110, 99,101, 0, 98, 83,111,117,110,100, 0, 77,101,116, 97, 83,116, 97, 99,107, 0, 87,105,112,101, 86, 97,114,115, + 0, 71,108,111,119, 86, 97,114,115, 0, 84,114, 97,110,115,102,111,114,109, 86, 97,114,115, 0, 83,111,108,105,100, 67,111,108, +111,114, 86, 97,114,115, 0, 83,112,101,101,100, 67,111,110,116,114,111,108, 86, 97,114,115, 0, 69,102,102,101, 99,116, 0, 66, +117,105,108,100, 69,102,102, 0, 80, 97,114,116, 69,102,102, 0, 80, 97,114,116,105, 99,108,101, 0, 87, 97,118,101, 69,102,102, + 0, 98, 80,114,111,112,101,114,116,121, 0, 98, 78,101, 97,114, 83,101,110,115,111,114, 0, 98, 77,111,117,115,101, 83,101,110, +115,111,114, 0, 98, 84,111,117, 99,104, 83,101,110,115,111,114, 0, 98, 75,101,121, 98,111, 97,114,100, 83,101,110,115,111,114, + 0, 98, 80,114,111,112,101,114,116,121, 83,101,110,115,111,114, 0, 98, 65, 99,116,117, 97,116,111,114, 83,101,110,115,111,114, + 0, 98, 68,101,108, 97,121, 83,101,110,115,111,114, 0, 98, 67,111,108,108,105,115,105,111,110, 83,101,110,115,111,114, 0, 98, + 82, 97,100, 97,114, 83,101,110,115,111,114, 0, 98, 82, 97,110,100,111,109, 83,101,110,115,111,114, 0, 98, 82, 97,121, 83,101, +110,115,111,114, 0, 98, 65,114,109, 97,116,117,114,101, 83,101,110,115,111,114, 0, 98, 77,101,115,115, 97,103,101, 83,101,110, +115,111,114, 0, 98, 83,101,110,115,111,114, 0, 98, 67,111,110,116,114,111,108,108,101,114, 0, 98, 74,111,121,115,116,105, 99, +107, 83,101,110,115,111,114, 0, 98, 69,120,112,114,101,115,115,105,111,110, 67,111,110,116, 0, 98, 80,121,116,104,111,110, 67, +111,110,116, 0, 98, 65, 99,116,117, 97,116,111,114, 0, 98, 65,100,100, 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, + 0, 98, 65, 99,116,105,111,110, 65, 99,116,117, 97,116,111,114, 0, 83,111,117,110,100, 51, 68, 0, 98, 83,111,117,110,100, 65, + 99,116,117, 97,116,111,114, 0, 98, 69,100,105,116, 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 83, 99,101, +110,101, 65, 99,116,117, 97,116,111,114, 0, 98, 80,114,111,112,101,114,116,121, 65, 99,116,117, 97,116,111,114, 0, 98, 79, 98, +106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 73,112,111, 65, 99,116,117, 97,116,111,114, 0, 98, 67, 97,109,101,114, + 97, 65, 99,116,117, 97,116,111,114, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 65, 99,116,117, 97,116,111,114, 0, 98, 71, +114,111,117,112, 65, 99,116,117, 97,116,111,114, 0, 98, 82, 97,110,100,111,109, 65, 99,116,117, 97,116,111,114, 0, 98, 77,101, +115,115, 97,103,101, 65, 99,116,117, 97,116,111,114, 0, 98, 71, 97,109,101, 65, 99,116,117, 97,116,111,114, 0, 98, 86,105,115, +105, 98,105,108,105,116,121, 65, 99,116,117, 97,116,111,114, 0, 98, 84,119,111, 68, 70,105,108,116,101,114, 65, 99,116,117, 97, +116,111,114, 0, 98, 80, 97,114,101,110,116, 65, 99,116,117, 97,116,111,114, 0, 98, 83,116, 97,116,101, 65, 99,116,117, 97,116, +111,114, 0, 98, 65,114,109, 97,116,117,114,101, 65, 99,116,117, 97,116,111,114, 0, 98, 83,116,101,101,114,105,110,103, 65, 99, +116,117, 97,116,111,114, 0, 71,114,111,117,112, 79, 98,106,101, 99,116, 0, 66,111,110,101, 0, 98, 65,114,109, 97,116,117,114, +101, 0, 98, 77,111,116,105,111,110, 80, 97,116,104, 86,101,114,116, 0, 98, 80,111,115,101, 67,104, 97,110,110,101,108, 0, 98, + 73, 75, 80, 97,114, 97,109, 0, 98, 73,116, 97,115, 99, 0, 98, 65, 99,116,105,111,110, 71,114,111,117,112, 0, 83,112, 97, 99, +101, 65, 99,116,105,111,110, 0, 98, 65, 99,116,105,111,110, 67,104, 97,110,110,101,108, 0, 98, 67,111,110,115,116,114, 97,105, +110,116, 67,104, 97,110,110,101,108, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 67,111,110,115,116,114, 97,105,110, +116, 84, 97,114,103,101,116, 0, 98, 80,121,116,104,111,110, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 75,105,110,101,109, + 97,116,105, 99, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,112,108,105,110,101, 73, 75, 67,111,110,115,116,114, 97,105, +110,116, 0, 98, 84,114, 97, 99,107, 84,111, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,111,116, 97,116,101, 76,105,107, +101, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 76,111, 99, 97,116,101, 76,105,107,101, 67,111,110,115,116,114, 97,105,110, +116, 0, 98, 83,105,122,101, 76,105,107,101, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83, 97,109,101, 86,111,108,117,109, +101, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 84,114, 97,110,115, 76,105,107,101, 67,111,110,115,116,114, 97,105,110,116, + 0, 98, 77,105,110, 77, 97,120, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 65, 99,116,105,111,110, 67,111,110,115,116,114, + 97,105,110,116, 0, 98, 76,111, 99,107, 84,114, 97, 99,107, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 68, 97,109,112, 84, +114, 97, 99,107, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 70,111,108,108,111,119, 80, 97,116,104, 67,111,110,115,116,114, + 97,105,110,116, 0, 98, 83,116,114,101,116, 99,104, 84,111, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,105,103,105,100, + 66,111,100,121, 74,111,105,110,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 67,108, 97,109,112, 84,111, 67,111,110,115, +116,114, 97,105,110,116, 0, 98, 67,104,105,108,100, 79,102, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 84,114, 97,110,115, +102,111,114,109, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 80,105,118,111,116, 67,111,110,115,116,114, 97,105,110,116, 0, + 98, 76,111, 99, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,111,116, 76,105,109,105,116, 67,111,110, +115,116,114, 97,105,110,116, 0, 98, 83,105,122,101, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 68,105, +115,116, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,104,114,105,110,107,119,114, 97,112, 67,111,110, +115,116,114, 97,105,110,116, 0, 98, 70,111,108,108,111,119, 84,114, 97, 99,107, 67,111,110,115,116,114, 97,105,110,116, 0, 98, + 67, 97,109,101,114, 97, 83,111,108,118,101,114, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 79, 98,106,101, 99,116, 83,111, +108,118,101,114, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 65, 99,116,105,111,110, 77,111,100,105,102,105,101,114, 0, 98, + 65, 99,116,105,111,110, 83,116,114,105,112, 0, 98, 78,111,100,101, 83,116, 97, 99,107, 0, 98, 78,111,100,101, 83,111, 99,107, +101,116, 0, 98, 78,111,100,101, 76,105,110,107, 0, 98, 78,111,100,101, 80,114,101,118,105,101,119, 0, 98, 78,111,100,101, 0, +117,105, 66,108,111, 99,107, 0, 98, 78,111,100,101, 84,121,112,101, 0, 98, 78,111,100,101, 84,114,101,101, 69,120,101, 99, 0, + 98, 78,111,100,101, 83,111, 99,107,101,116, 86, 97,108,117,101, 73,110,116, 0, 98, 78,111,100,101, 83,111, 99,107,101,116, 86, + 97,108,117,101, 70,108,111, 97,116, 0, 98, 78,111,100,101, 83,111, 99,107,101,116, 86, 97,108,117,101, 66,111,111,108,101, 97, +110, 0, 98, 78,111,100,101, 83,111, 99,107,101,116, 86, 97,108,117,101, 86,101, 99,116,111,114, 0, 98, 78,111,100,101, 83,111, + 99,107,101,116, 86, 97,108,117,101, 82, 71, 66, 65, 0, 78,111,100,101, 73,109, 97,103,101, 65,110,105,109, 0, 78,111,100,101, + 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 68, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 66,105,108, 97,116, +101,114, 97,108, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 72,117,101, 83, 97,116, 0, 78,111,100,101, 73,109, 97,103, +101, 70,105,108,101, 0, 78,111,100,101, 73,109, 97,103,101, 77,117,108,116,105, 70,105,108,101, 0, 78,111,100,101, 73,109, 97, +103,101, 77,117,108,116,105, 70,105,108,101, 83,111, 99,107,101,116, 0, 78,111,100,101, 67,104,114,111,109, 97, 0, 78,111,100, +101, 84,119,111, 88, 89,115, 0, 78,111,100,101, 84,119,111, 70,108,111, 97,116,115, 0, 78,111,100,101, 71,101,111,109,101,116, +114,121, 0, 78,111,100,101, 86,101,114,116,101,120, 67,111,108, 0, 78,111,100,101, 68,101,102,111, 99,117,115, 0, 78,111,100, +101, 83, 99,114,105,112,116, 68,105, 99,116, 0, 78,111,100,101, 71,108, 97,114,101, 0, 78,111,100,101, 84,111,110,101,109, 97, +112, 0, 78,111,100,101, 76,101,110,115, 68,105,115,116, 0, 78,111,100,101, 67,111,108,111,114, 66, 97,108, 97,110, 99,101, 0, + 78,111,100,101, 67,111,108,111,114,115,112,105,108,108, 0, 78,111,100,101, 84,101,120, 66, 97,115,101, 0, 78,111,100,101, 84, +101,120, 83,107,121, 0, 78,111,100,101, 84,101,120, 73,109, 97,103,101, 0, 78,111,100,101, 84,101,120, 67,104,101, 99,107,101, +114, 0, 78,111,100,101, 84,101,120, 69,110,118,105,114,111,110,109,101,110,116, 0, 78,111,100,101, 84,101,120, 71,114, 97,100, +105,101,110,116, 0, 78,111,100,101, 84,101,120, 78,111,105,115,101, 0, 78,111,100,101, 84,101,120, 86,111,114,111,110,111,105, + 0, 78,111,100,101, 84,101,120, 77,117,115,103,114, 97,118,101, 0, 78,111,100,101, 84,101,120, 87, 97,118,101, 0, 78,111,100, +101, 84,101,120, 77, 97,103,105, 99, 0, 78,111,100,101, 83,104, 97,100,101,114, 65,116,116,114,105, 98,117,116,101, 0, 84,101, +120, 78,111,100,101, 79,117,116,112,117,116, 0, 67,117,114,118,101, 77, 97,112, 80,111,105,110,116, 0, 67,117,114,118,101, 77, + 97,112, 0, 66,114,117,115,104, 67,108,111,110,101, 0, 67,117,115,116,111,109, 68, 97,116, 97, 76, 97,121,101,114, 0, 67,117, +115,116,111,109, 68, 97,116, 97, 69,120,116,101,114,110, 97,108, 0, 72, 97,105,114, 75,101,121, 0, 80, 97,114,116,105, 99,108, +101, 75,101,121, 0, 66,111,105,100, 80, 97,114,116,105, 99,108,101, 0, 66,111,105,100, 68, 97,116, 97, 0, 80, 97,114,116,105, + 99,108,101, 83,112,114,105,110,103, 0, 67,104,105,108,100, 80, 97,114,116,105, 99,108,101, 0, 80, 97,114,116,105, 99,108,101, + 84, 97,114,103,101,116, 0, 80, 97,114,116,105, 99,108,101, 68,117,112,108,105, 87,101,105,103,104,116, 0, 80, 97,114,116,105, + 99,108,101, 68, 97,116, 97, 0, 83, 80, 72, 70,108,117,105,100, 83,101,116,116,105,110,103,115, 0, 80, 97,114,116,105, 99,108, +101, 83,101,116,116,105,110,103,115, 0, 66,111,105,100, 83,101,116,116,105,110,103,115, 0, 80, 97,114,116,105, 99,108,101, 67, + 97, 99,104,101, 75,101,121, 0, 75, 68, 84,114,101,101, 0, 80, 97,114,116,105, 99,108,101, 68,114, 97,119, 68, 97,116, 97, 0, + 76,105,110,107, 78,111,100,101, 0, 98, 71, 80, 68,115,112,111,105,110,116, 0, 98, 71, 80, 68,115,116,114,111,107,101, 0, 98, + 71, 80, 68,102,114, 97,109,101, 0, 98, 71, 80, 68,108, 97,121,101,114, 0, 82,101,112,111,114,116, 76,105,115,116, 0,119,109, + 87,105,110,100,111,119, 77, 97,110, 97,103,101,114, 0,119,109, 87,105,110,100,111,119, 0,119,109, 75,101,121, 67,111,110,102, +105,103, 0,119,109, 69,118,101,110,116, 0,119,109, 83,117, 98, 87,105,110,100,111,119, 0,119,109, 71,101,115,116,117,114,101, + 0,119,109, 75,101,121, 77, 97,112, 73,116,101,109, 0, 80,111,105,110,116,101,114, 82, 78, 65, 0,119,109, 75,101,121, 77, 97, +112, 68,105,102,102, 73,116,101,109, 0,119,109, 75,101,121, 77, 97,112, 0,119,109, 79,112,101,114, 97,116,111,114, 84,121,112, +101, 0, 70, 77,111,100,105,102,105,101,114, 0, 70, 77,111,100, 95, 71,101,110,101,114, 97,116,111,114, 0, 70, 77,111,100, 95, + 70,117,110, 99,116,105,111,110, 71,101,110,101,114, 97,116,111,114, 0, 70, 67, 77, 95, 69,110,118,101,108,111,112,101, 68, 97, +116, 97, 0, 70, 77,111,100, 95, 69,110,118,101,108,111,112,101, 0, 70, 77,111,100, 95, 67,121, 99,108,101,115, 0, 70, 77,111, +100, 95, 80,121,116,104,111,110, 0, 70, 77,111,100, 95, 76,105,109,105,116,115, 0, 70, 77,111,100, 95, 78,111,105,115,101, 0, + 70, 77,111,100, 95, 83,116,101,112,112,101,100, 0, 68,114,105,118,101,114, 84, 97,114,103,101,116, 0, 68,114,105,118,101,114, + 86, 97,114, 0, 67,104, 97,110,110,101,108, 68,114,105,118,101,114, 0, 70, 80,111,105,110,116, 0, 70, 67,117,114,118,101, 0, + 65,110,105,109, 77, 97,112, 80, 97,105,114, 0, 65,110,105,109, 77, 97,112,112,101,114, 0, 78,108, 97, 83,116,114,105,112, 0, + 78,108, 97, 84,114, 97, 99,107, 0, 75, 83, 95, 80, 97,116,104, 0, 75,101,121,105,110,103, 83,101,116, 0, 65,110,105,109, 79, +118,101,114,114,105,100,101, 0, 73,100, 65,100,116, 84,101,109,112,108, 97,116,101, 0, 66,111,105,100, 82,117,108,101, 0, 66, +111,105,100, 82,117,108,101, 71,111, 97,108, 65,118,111,105,100, 0, 66,111,105,100, 82,117,108,101, 65,118,111,105,100, 67,111, +108,108,105,115,105,111,110, 0, 66,111,105,100, 82,117,108,101, 70,111,108,108,111,119, 76,101, 97,100,101,114, 0, 66,111,105, +100, 82,117,108,101, 65,118,101,114, 97,103,101, 83,112,101,101,100, 0, 66,111,105,100, 82,117,108,101, 70,105,103,104,116, 0, + 66,111,105,100, 83,116, 97,116,101, 0, 70, 76, 85, 73, 68, 95, 51, 68, 0, 87, 84, 85, 82, 66, 85, 76, 69, 78, 67, 69, 0, 83, +112,101, 97,107,101,114, 0, 77,111,118,105,101, 67,108,105,112, 80,114,111,120,121, 0, 77,111,118,105,101, 67,108,105,112, 67, + 97, 99,104,101, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, + 84,114, 97, 99,107, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, 77, 97,114,107,101,114, 0, 77,111,118,105,101, 82, +101, 99,111,110,115,116,114,117, 99,116,101,100, 67, 97,109,101,114, 97, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, + 67, 97,109,101,114, 97, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, 83,101,116,116,105,110,103,115, 0, 77,111,118, +105,101, 84,114, 97, 99,107,105,110,103, 83,116, 97, 98,105,108,105,122, 97,116,105,111,110, 0, 77,111,118,105,101, 84,114, 97, + 99,107,105,110,103, 82,101, 99,111,110,115,116,114,117, 99,116,105,111,110, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110, +103, 79, 98,106,101, 99,116, 0, 77,111,118,105,101, 84,114, 97, 99,107,105,110,103, 83,116, 97,116,115, 0, 68,121,110, 97,109, +105, 99, 80, 97,105,110,116, 83,117,114,102, 97, 99,101, 0, 80, 97,105,110,116, 83,117,114,102, 97, 99,101, 68, 97,116, 97, 0, + 84, 76, 69, 78, 1, 0, 1, 0, 2, 0, 2, 0, 4, 0, 4, 0, 4, 0, 4, 0, 8, 0, 8, 0, 8, 0, 0, 0, 16, 0, 24, 0, + 16, 0, 4, 0, 8, 0, 12, 0, 16, 0, 16, 0, 32, 0,128, 0,120, 0,152, 8, 0, 0, 40, 0,144, 0,112, 5,112, 0, 36, 0, + 56, 0,160, 0,192, 0,224, 0, 96, 0, 40, 0, 48, 0,224, 0, 16, 0,200, 0, 40, 0,216, 11, 48, 5, 0, 0, 0, 0, 0, 0, + 56, 1,168, 1,216, 4, 24, 0, 8, 3,200, 0, 0, 0,104, 0, 64, 1, 56, 4, 80, 0, 24, 1,144, 0, 56, 3, 16, 2, 88, 0, + 16, 0,128, 3,152, 0,136, 4, 0, 0,104, 0,104, 0, 0, 1, 80, 0, 8, 0, 16, 0, 32, 0, 0, 0, 8, 2, 0, 0, 0, 0, + 0, 0,232, 4, 8, 0, 12, 0, 16, 0, 8, 0, 12, 0, 4, 0, 20, 0, 48, 0, 64, 0, 20, 0, 12, 0, 16, 0, 4, 0, 8, 0, + 0, 0,176, 0,144, 1, 8, 0, 4, 0, 4, 0, 0, 1, 32, 0, 8, 0, 24, 0, 16, 0, 64, 0, 24, 0, 12, 0, 64, 0, 4, 0, +112, 0,200, 0,136, 0,192, 0,192, 0,128, 0,192, 0,192, 0,128, 0,120, 0,200, 0,120, 0,144, 0, 16, 1, 56, 0,192, 0, + 24, 1, 40, 1,120, 0,184, 0,200, 0, 64, 1,200, 0, 88, 1,112, 0,168, 0, 0, 0,152, 0, 48, 0, 40, 5,192, 0, 0, 0, +152, 0, 0, 0, 0, 0,128, 0, 8, 0, 8, 0,112, 1,144, 0,152, 2,136, 0,192, 0,120, 0,128, 0,224, 4,208, 0,200, 0, +112, 0,208, 0,144, 0, 16, 5, 0, 0, 0, 0, 48, 1,104, 1,160, 1,104, 1,136, 0,104, 0,112, 0,128, 0, 16, 0, 96, 1, + 88, 0, 0, 0,200, 0,216, 0,152, 0, 48, 0, 24, 0,120, 0,152, 0,216, 1, 0, 1,184, 0, 0, 0, 72, 0, 32, 0,176, 0, + 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 12, 0, 24, 2, 40, 0,184, 0,152, 0, 64, 0, 72, 0, 32, 0,120, 0, 24, 0, 56, 9, + 64, 0, 24, 0, 16, 0, 56, 0,168, 0, 96, 0, 24, 0, 88, 6, 48, 0, 16, 0,168, 0, 96, 0, 24, 0, 56, 0,120, 0, 16, 0, +232, 1, 32, 0, 8, 0, 24, 0, 80, 8, 0, 0, 0, 0,192, 8,104, 0, 8, 0,112, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 96, 1, 56, 0,144, 0, 64, 0,240, 0,112, 0,248, 0,240, 0,160, 7,104, 0, 0, 0,168, 0, 0, 0, 24, 1, 16, 0, 16, 0, + 40, 33,128, 16, 24, 16,216, 0,160, 2,168, 5, 64, 0, 24, 0,208, 0, 48, 1, 72, 0, 40, 0,136, 1,104, 0, 48, 1, 56, 0, + 24, 4, 32, 0,232, 0, 32, 0, 32, 0, 8, 0, 80, 3,224, 1, 16, 0,168, 36, 80, 0, 56, 0,112, 38, 8, 1, 32, 0, 40, 0, + 88, 1, 0, 0, 0, 0,160, 0, 0, 0, 40, 1, 0, 0, 48, 4, 8, 1, 16, 0, 8, 0, 44, 0, 16, 4, 72, 3,200, 4, 80, 1, +208, 4, 32, 0, 12, 0, 24, 0, 32, 0, 16, 0, 24, 0, 24, 0, 32, 0,136, 1, 0, 0, 64, 0, 96, 0, 80, 0, 8, 0, 80, 0, +136, 0,200, 0, 72, 0, 8, 0,136, 0, 76, 0, 72, 0,204, 0,136, 0,136, 0,128, 0,136, 0, 92, 0,128, 0, 80, 0,112, 0, + 16, 0,168, 0, 32, 0, 72, 0,120, 0, 24, 0,144, 0,112, 0,148, 0, 32, 0,128, 0, 88, 0, 88, 0,208, 0,140, 0, 4, 0, + 24, 0, 16, 0, 8, 0,160, 0, 48, 0, 40, 0, 72, 1, 0, 1, 16, 0, 32, 2, 4, 0, 40, 0,120, 0, 72, 1,120, 0, 56, 0, +120, 0,160, 0,112, 0,184, 0, 24, 0, 88, 0, 80, 0, 80, 0, 80, 0, 8, 0, 72, 0,104, 0,104, 0, 80, 0, 80, 0, 24, 0, + 88, 0,104, 0, 16, 0,144, 0,128, 0, 88, 0, 28, 0, 28, 0, 28, 0, 88, 0, 24, 0,160, 0, 16, 0,152, 0, 72, 0,168, 0, + 48, 0,208, 0, 56, 0, 16, 0, 88, 1, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 4, 0, 24, 0, 16, 0, 16, 0, 40, 0, 28, 0, + 12, 0, 12, 0, 32, 4, 40, 4, 32, 0, 44, 0, 24, 0, 8, 0,128, 0, 64, 0, 32, 0, 16, 0, 32, 0, 32, 0, 8, 0, 96, 0, + 20, 0,200, 3,216, 3,208, 3,200, 3,208, 3,208, 3,200, 3,208, 3,208, 3,208, 3,208, 3, 64, 0, 64, 0, 12, 0, 56, 0, + 24, 0,104, 0, 0, 4, 24, 0, 56, 0, 56, 0, 20, 0, 16, 0, 64, 0, 40, 0, 32, 0,192, 0, 60, 0, 16, 3,104, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16, 0, 32, 0, 40, 0,192, 0, 40, 0, 88, 1, 0, 1,168, 0, 0, 0, 0, 0, 0, 0,120, 0, 0, 0, + 32, 0,136, 0, 0, 0,120, 0, 24, 0, 24, 0, 16, 0, 24, 0, 8, 0, 16, 0, 24, 0, 20, 0, 20, 0, 56, 0, 24, 2, 40, 1, + 16, 0,104, 0, 0, 1, 40, 0,208, 0,104, 0,112, 0,216, 1, 32, 0,128, 0, 56, 0, 80, 0, 64, 0,104, 0, 72, 0, 64, 0, +128, 0, 0, 0, 0, 0,184, 0, 8, 3, 0, 0,248, 0,192, 0, 16, 0, 72, 0, 48, 0, 64, 0, 56, 0, 24, 0,128, 0, 0, 1, + 16, 6, 0, 0, 83, 84, 82, 67,207, 1, 0, 0, 12, 0, 2, 0, 12, 0, 0, 0, 12, 0, 1, 0, 13, 0, 3, 0, 13, 0, 0, 0, + 13, 0, 1, 0, 11, 0, 2, 0, 14, 0, 2, 0, 11, 0, 3, 0, 11, 0, 4, 0, 15, 0, 2, 0, 2, 0, 5, 0, 2, 0, 6, 0, + 16, 0, 2, 0, 7, 0, 5, 0, 7, 0, 6, 0, 17, 0, 3, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 18, 0, 4, 0, + 4, 0, 8, 0, 4, 0, 9, 0, 4, 0, 10, 0, 4, 0, 11, 0, 19, 0, 4, 0, 7, 0, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, + 7, 0, 11, 0, 20, 0, 4, 0, 11, 0, 12, 0, 14, 0, 13, 0, 4, 0, 14, 0, 4, 0, 15, 0, 21, 0, 10, 0, 21, 0, 0, 0, + 21, 0, 1, 0, 0, 0, 16, 0, 0, 0, 17, 0, 2, 0, 18, 0, 0, 0, 19, 0, 4, 0, 20, 0, 20, 0, 21, 0, 4, 0, 22, 0, + 4, 0, 23, 0, 22, 0, 11, 0, 11, 0, 0, 0, 11, 0, 1, 0, 22, 0, 24, 0, 23, 0, 25, 0, 0, 0, 26, 0, 2, 0, 27, 0, + 2, 0, 28, 0, 2, 0, 18, 0, 4, 0, 29, 0, 4, 0, 30, 0, 21, 0, 31, 0, 23, 0, 8, 0, 22, 0, 32, 0, 22, 0, 33, 0, + 24, 0, 34, 0, 0, 0, 35, 0, 0, 0, 36, 0, 4, 0, 37, 0, 4, 0, 27, 0, 23, 0, 38, 0, 25, 0, 5, 0, 4, 0, 39, 0, + 4, 0, 40, 0, 2, 0, 41, 0, 2, 0, 42, 0, 4, 0, 43, 0, 26, 0, 6, 0, 27, 0, 44, 0, 2, 0, 45, 0, 2, 0, 46, 0, + 2, 0, 16, 0, 2, 0, 18, 0, 0, 0, 47, 0, 28, 0, 21, 0, 28, 0, 0, 0, 28, 0, 1, 0, 29, 0, 48, 0, 30, 0, 49, 0, + 19, 0, 50, 0, 19, 0, 51, 0, 2, 0, 45, 0, 2, 0, 46, 0, 2, 0, 52, 0, 2, 0, 53, 0, 2, 0, 54, 0, 2, 0, 55, 0, + 2, 0, 18, 0, 2, 0, 56, 0, 7, 0, 10, 0, 7, 0, 11, 0, 4, 0, 57, 0, 7, 0, 58, 0, 7, 0, 59, 0, 7, 0, 60, 0, + 26, 0, 61, 0, 31, 0, 7, 0, 22, 0, 32, 0, 14, 0, 62, 0, 19, 0, 63, 0, 2, 0, 45, 0, 2, 0, 64, 0, 2, 0, 65, 0, + 2, 0, 27, 0, 32, 0, 16, 0, 32, 0, 0, 0, 32, 0, 1, 0, 7, 0, 66, 0, 7, 0, 60, 0, 2, 0, 16, 0, 2, 0, 67, 0, + 2, 0, 68, 0, 2, 0, 18, 0, 4, 0, 69, 0, 4, 0, 70, 0, 11, 0, 2, 0, 7, 0, 71, 0, 0, 0, 19, 0, 0, 0, 72, 0, + 7, 0, 73, 0, 7, 0, 74, 0, 33, 0, 15, 0, 22, 0, 32, 0, 34, 0, 75, 0, 32, 0, 76, 0, 0, 0, 77, 0, 4, 0, 78, 0, + 4, 0, 27, 0, 14, 0, 79, 0, 31, 0, 80, 0, 22, 0, 81, 0, 2, 0, 16, 0, 2, 0, 82, 0, 2, 0, 83, 0, 2, 0, 18, 0, + 7, 0, 84, 0, 4, 0, 85, 0, 35, 0, 6, 0, 35, 0, 0, 0, 35, 0, 1, 0, 0, 0, 86, 0, 0, 0, 87, 0, 4, 0, 22, 0, + 4, 0, 88, 0, 36, 0, 10, 0, 36, 0, 0, 0, 36, 0, 1, 0, 4, 0, 89, 0, 4, 0, 90, 0, 4, 0, 91, 0, 4, 0, 67, 0, + 4, 0, 13, 0, 4, 0, 92, 0, 0, 0, 93, 0, 0, 0, 94, 0, 37, 0, 15, 0, 22, 0, 32, 0, 0, 0, 95, 0, 4, 0, 92, 0, + 4, 0, 96, 0, 14, 0, 97, 0, 35, 0, 98, 0, 35, 0, 99, 0, 4, 0,100, 0, 4, 0,101, 0, 14, 0,102, 0, 0, 0,103, 0, + 4, 0,104, 0, 4, 0,105, 0, 11, 0,106, 0, 8, 0,107, 0, 38, 0, 3, 0, 4, 0,108, 0, 4, 0,109, 0, 11, 0, 2, 0, + 39, 0, 20, 0, 22, 0, 32, 0, 34, 0, 75, 0, 0, 0, 16, 0, 0, 0,110, 0, 2, 0, 18, 0, 7, 0,111, 0, 7, 0,112, 0, + 7, 0,113, 0, 7, 0,114, 0, 7, 0,115, 0, 7, 0,116, 0, 7, 0,117, 0, 7, 0,118, 0, 7, 0,119, 0, 7, 0,120, 0, + 7, 0,121, 0, 31, 0, 80, 0, 27, 0,122, 0, 0, 0,123, 0, 0, 0,124, 0, 40, 0, 14, 0, 41, 0,125, 0, 4, 0,126, 0, + 4, 0,127, 0, 4, 0,128, 0, 4, 0,129, 0, 0, 0,130, 0, 0, 0,131, 0, 0, 0,132, 0, 0, 0, 27, 0, 2, 0,133, 0, + 2, 0,134, 0, 2, 0,135, 0, 2, 0, 18, 0, 4, 0, 30, 0, 42, 0, 33, 0, 22, 0, 32, 0, 0, 0, 35, 0, 14, 0,136, 0, + 43, 0,137, 0, 44, 0,138, 0, 45, 0,139, 0, 45, 0,140, 0, 2, 0,141, 0, 2, 0,142, 0, 2, 0,132, 0, 2, 0, 18, 0, + 2, 0,143, 0, 2, 0, 16, 0, 4, 0,144, 0, 2, 0,145, 0, 2, 0,146, 0, 2, 0,147, 0, 2, 0,148, 0, 2, 0,149, 0, + 2, 0,150, 0, 4, 0,151, 0, 4, 0,152, 0, 38, 0,153, 0, 25, 0,154, 0, 7, 0,155, 0, 4, 0,156, 0, 2, 0,157, 0, + 2, 0,158, 0, 2, 0,159, 0, 0, 0,160, 0, 0, 0,161, 0, 7, 0,162, 0, 7, 0,163, 0, 46, 0, 65, 0, 2, 0,164, 0, + 2, 0,165, 0, 2, 0,166, 0, 2, 0,167, 0, 27, 0,168, 0, 47, 0,169, 0, 0, 0,170, 0, 0, 0,171, 0, 0, 0,172, 0, + 0, 0,173, 0, 0, 0,174, 0, 7, 0,175, 0, 7, 0,176, 0, 7, 0,177, 0, 2, 0,178, 0, 2, 0,179, 0, 2, 0,180, 0, + 2, 0,181, 0, 2, 0,182, 0, 2, 0,183, 0, 0, 0,184, 0, 0, 0,124, 0, 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0, + 7, 0,188, 0, 7, 0,189, 0, 7, 0, 56, 0, 7, 0,190, 0, 7, 0,191, 0, 7, 0,192, 0, 7, 0,193, 0, 7, 0,194, 0, + 7, 0,195, 0, 7, 0,196, 0, 7, 0,197, 0, 7, 0,198, 0, 7, 0,199, 0, 7, 0,200, 0, 7, 0,201, 0, 7, 0,202, 0, + 7, 0,203, 0, 7, 0,204, 0, 7, 0,205, 0, 7, 0,206, 0, 7, 0,207, 0, 7, 0,208, 0, 7, 0,209, 0, 7, 0,210, 0, + 7, 0,211, 0, 7, 0,212, 0, 7, 0,213, 0, 7, 0,214, 0, 7, 0,215, 0, 7, 0,216, 0, 7, 0,217, 0, 7, 0,218, 0, + 7, 0,219, 0, 7, 0,220, 0, 7, 0,221, 0, 7, 0,222, 0, 7, 0,223, 0, 7, 0,224, 0, 7, 0,225, 0, 7, 0,226, 0, + 48, 0, 15, 0, 0, 0, 35, 0, 11, 0,227, 0, 0, 0,228, 0, 0, 0,229, 0, 4, 0,230, 0, 4, 0,231, 0, 11, 0,232, 0, + 7, 0,233, 0, 7, 0,234, 0, 7, 0,235, 0, 4, 0,236, 0, 11, 0,237, 0, 11, 0,238, 0, 4, 0,239, 0, 4, 0, 27, 0, + 49, 0, 6, 0, 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0, 7, 0,240, 0, 7, 0, 66, 0, 4, 0, 63, 0, 50, 0, 5, 0, + 2, 0, 18, 0, 2, 0, 37, 0, 2, 0, 63, 0, 2, 0,241, 0, 49, 0,235, 0, 51, 0, 17, 0, 27, 0,168, 0, 42, 0,242, 0, + 52, 0,243, 0, 7, 0,244, 0, 7, 0,245, 0, 2, 0, 16, 0, 2, 0,246, 0, 7, 0,112, 0, 7, 0,113, 0, 7, 0,247, 0, + 4, 0,248, 0, 2, 0,249, 0, 2, 0,250, 0, 4, 0,132, 0, 4, 0,144, 0, 2, 0,251, 0, 2, 0,252, 0, 53, 0, 25, 0, + 2, 0, 18, 0, 2, 0,253, 0, 7, 0,254, 0, 7, 0,255, 0, 2, 0,143, 0, 2, 0, 0, 1, 4, 0, 1, 1, 4, 0, 2, 1, + 27, 0,168, 0, 4, 0, 3, 1, 2, 0, 4, 1, 2, 0, 5, 1, 11, 0, 6, 1, 7, 0, 7, 1, 7, 0, 8, 1, 2, 0, 9, 1, + 2, 0, 10, 1, 2, 0, 11, 1, 2, 0, 12, 1, 7, 0, 13, 1, 7, 0, 14, 1, 7, 0, 15, 1, 7, 0, 16, 1, 50, 0, 17, 1, + 54, 0, 18, 1, 55, 0, 13, 0, 4, 0, 19, 1, 4, 0, 20, 1, 2, 0, 21, 1, 2, 0, 18, 0, 2, 0, 22, 1, 2, 0, 23, 1, + 27, 0,168, 0, 7, 0, 24, 1, 4, 0, 25, 1, 0, 0, 26, 1, 7, 0, 27, 1, 4, 0, 28, 1, 4, 0,132, 0, 56, 0, 4, 0, + 27, 0,168, 0, 0, 0, 29, 1, 4, 0, 30, 1, 4, 0, 27, 0, 47, 0, 64, 0, 22, 0, 32, 0, 34, 0, 75, 0, 7, 0, 31, 1, + 7, 0, 32, 1, 7, 0, 33, 1, 7, 0, 34, 1, 7, 0, 35, 1, 7, 0, 36, 1, 7, 0, 37, 1, 7, 0, 38, 1, 7, 0, 39, 1, + 7, 0, 30, 0, 7, 0, 40, 1, 7, 0, 41, 1, 7, 0, 42, 1, 7, 0, 43, 1, 7, 0, 44, 1, 7, 0, 45, 1, 7, 0, 46, 1, + 7, 0, 47, 1, 7, 0, 48, 1, 7, 0, 49, 1, 7, 0, 50, 1, 7, 0, 51, 1, 2, 0, 52, 1, 2, 0, 53, 1, 2, 0, 54, 1, + 2, 0, 55, 1, 2, 0, 56, 1, 2, 0, 57, 1, 2, 0, 58, 1, 2, 0, 18, 0, 2, 0, 16, 0, 2, 0,246, 0, 7, 0, 59, 1, + 7, 0, 60, 1, 7, 0, 61, 1, 7, 0, 62, 1, 4, 0, 63, 1, 4, 0, 64, 1, 2, 0, 65, 1, 2, 0, 66, 1, 2, 0, 22, 1, + 2, 0,130, 0, 4, 0, 22, 0, 4, 0,127, 0, 4, 0,128, 0, 4, 0,129, 0, 7, 0, 67, 1, 7, 0, 68, 1, 7, 0, 67, 0, + 40, 0, 69, 1, 57, 0, 70, 1, 31, 0, 80, 0, 42, 0,242, 0, 48, 0, 71, 1, 50, 0, 17, 1, 51, 0, 72, 1, 25, 0,154, 0, + 53, 0, 73, 1, 55, 0, 74, 1, 56, 0, 75, 1, 0, 0, 76, 1, 0, 0,124, 0, 58, 0, 13, 0, 7, 0, 77, 1, 7, 0, 78, 1, + 7, 0,176, 0, 4, 0, 18, 0, 0, 0,171, 0, 0, 0,172, 0, 0, 0,173, 0, 0, 0,174, 0, 4, 0, 27, 0, 7, 0, 79, 1, + 7, 0, 80, 1, 7, 0, 81, 1, 27, 0, 44, 0, 59, 0, 9, 0, 50, 0, 82, 1, 7, 0, 33, 1, 7, 0, 34, 1, 7, 0, 35, 1, + 4, 0, 18, 0, 7, 0, 83, 1, 7, 0, 84, 1, 4, 0, 85, 1, 4, 0, 86, 1, 60, 0, 74, 0, 22, 0, 32, 0, 34, 0, 75, 0, + 2, 0, 16, 0, 2, 0, 18, 0, 4, 0, 87, 1, 2, 0,179, 0, 2, 0, 88, 1, 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0, + 7, 0,188, 0, 7, 0, 89, 1, 7, 0, 90, 1, 7, 0, 91, 1, 7, 0, 92, 1, 7, 0, 93, 1, 7, 0, 94, 1, 7, 0, 95, 1, + 7, 0, 96, 1, 7, 0, 97, 1, 7, 0, 98, 1, 7, 0, 99, 1, 54, 0,100, 1, 2, 0,253, 0, 2, 0, 30, 0, 7, 0,112, 0, + 7, 0,113, 0, 7, 0,101, 1, 7, 0,102, 1, 7, 0,103, 1, 7, 0,104, 1, 7, 0,105, 1, 2, 0,106, 1, 2, 0,107, 1, + 2, 0,108, 1, 2, 0,109, 1, 0, 0,110, 1, 0, 0,111, 1, 2, 0,112, 1, 2, 0,113, 1, 2, 0,114, 1, 2, 0,115, 1, + 2, 0,116, 1, 7, 0,117, 1, 7, 0,118, 1, 7, 0,119, 1, 7, 0,120, 1, 2, 0,121, 1, 2, 0, 67, 0, 2, 0,122, 1, + 2, 0,123, 1, 2, 0,124, 1, 2, 0,125, 1, 7, 0,126, 1, 7, 0,127, 1, 7, 0,128, 1, 7, 0,129, 1, 7, 0,130, 1, + 7, 0,131, 1, 7, 0,132, 1, 7, 0,133, 1, 7, 0,134, 1, 7, 0,135, 1, 7, 0,136, 1, 7, 0,137, 1, 2, 0,138, 1, + 0, 0,139, 1, 31, 0, 80, 0, 46, 0,140, 1, 2, 0,141, 1, 2, 0, 76, 1, 0, 0,142, 1, 25, 0,154, 0, 57, 0, 70, 1, + 61, 0, 18, 0, 7, 0,143, 1, 7, 0,144, 1, 7, 0,145, 1, 7, 0,146, 1, 7, 0,147, 1, 7, 0,148, 1, 7, 0,149, 1, + 7, 0,150, 1, 7, 0,151, 1, 7, 0,152, 1, 2, 0,153, 1, 2, 0,154, 1, 2, 0,155, 1, 2, 0,156, 1, 7, 0,157, 1, + 7, 0,158, 1, 7, 0,159, 1, 7, 0,160, 1, 62, 0, 4, 0, 4, 0, 18, 0, 4, 0,161, 1, 4, 0,162, 1, 4, 0, 67, 0, + 63, 0,126, 0, 22, 0, 32, 0, 34, 0, 75, 0, 2, 0,163, 1, 2, 0, 18, 0, 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0, + 7, 0,164, 1, 7, 0,165, 1, 7, 0,166, 1, 7, 0,167, 1, 7, 0,168, 1, 7, 0,169, 1, 7, 0,170, 1, 7, 0,171, 1, + 7, 0,172, 1, 7, 0,173, 1, 7, 0,174, 1, 7, 0,175, 1, 7, 0,176, 1, 7, 0,177, 1, 7, 0,178, 1, 7, 0,179, 1, + 7, 0,180, 1, 7, 0,181, 1, 7, 0,182, 1, 7, 0,183, 1, 61, 0,184, 1, 62, 0,185, 1, 7, 0,186, 1, 7, 0,187, 1, + 7, 0,188, 1, 7, 0,189, 1, 7, 0,190, 1, 7, 0,191, 1, 7, 0,192, 1, 2, 0,193, 1, 2, 0,194, 1, 2, 0,195, 1, + 0, 0,196, 1, 0, 0,197, 1, 7, 0,198, 1, 7, 0,199, 1, 2, 0,200, 1, 2, 0,201, 1, 7, 0,202, 1, 7, 0,203, 1, + 7, 0,204, 1, 7, 0,205, 1, 2, 0,206, 1, 2, 0,207, 1, 4, 0, 87, 1, 4, 0,208, 1, 2, 0,209, 1, 2, 0,210, 1, + 2, 0,211, 1, 2, 0,212, 1, 7, 0,213, 1, 7, 0,214, 1, 7, 0,215, 1, 7, 0,216, 1, 7, 0,217, 1, 7, 0,218, 1, + 7, 0,219, 1, 7, 0,220, 1, 7, 0,221, 1, 7, 0,222, 1, 0, 0,223, 1, 7, 0,224, 1, 7, 0,225, 1, 7, 0,226, 1, + 4, 0,227, 1, 0, 0,228, 1, 0, 0,122, 1, 0, 0,229, 1, 0, 0, 76, 1, 2, 0,230, 1, 2, 0,231, 1, 2, 0,141, 1, + 2, 0,232, 1, 2, 0,233, 1, 2, 0,234, 1, 7, 0,235, 1, 7, 0,236, 1, 7, 0,237, 1, 7, 0,238, 1, 7, 0,239, 1, + 2, 0,164, 0, 2, 0,165, 0, 50, 0,240, 1, 50, 0,241, 1, 0, 0,242, 1, 0, 0,243, 1, 0, 0,244, 1, 0, 0,245, 1, + 2, 0,246, 1, 2, 0,247, 1, 7, 0,248, 1, 7, 0,249, 1, 46, 0,140, 1, 57, 0, 70, 1, 31, 0, 80, 0, 64, 0,250, 1, + 25, 0,154, 0, 7, 0,251, 1, 7, 0,252, 1, 7, 0,253, 1, 7, 0,254, 1, 7, 0,255, 1, 2, 0, 0, 2, 2, 0, 30, 0, + 7, 0, 1, 2, 7, 0, 2, 2, 7, 0, 3, 2, 7, 0, 4, 2, 7, 0, 5, 2, 7, 0, 6, 2, 7, 0, 7, 2, 7, 0, 8, 2, + 7, 0, 9, 2, 2, 0, 10, 2, 2, 0, 11, 2, 4, 0, 12, 2, 2, 0, 13, 2, 2, 0, 14, 2, 14, 0, 15, 2, 65, 0, 4, 0, + 22, 0, 32, 0, 0, 0, 35, 0, 66, 0, 2, 0, 38, 0,153, 0, 67, 0, 20, 0, 67, 0, 0, 0, 67, 0, 1, 0, 68, 0, 16, 2, + 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 17, 2, 2, 0, 18, 2, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 7, 0, 19, 2, + 7, 0, 20, 2, 7, 0, 21, 2, 7, 0, 22, 2, 7, 0, 23, 2, 7, 0, 24, 2, 7, 0, 25, 2, 7, 0, 22, 0, 7, 0, 26, 2, + 7, 0, 27, 2, 69, 0, 20, 0, 22, 0, 32, 0, 34, 0, 75, 0, 68, 0, 16, 2, 14, 0, 28, 2, 14, 0, 29, 2, 14, 0, 30, 2, + 31, 0, 80, 0, 63, 0, 31, 2, 0, 0, 18, 0, 0, 0, 32, 2, 2, 0, 33, 2, 2, 0,178, 0, 2, 0, 27, 0, 7, 0, 77, 1, + 7, 0,176, 0, 7, 0, 78, 1, 7, 0, 34, 2, 7, 0, 35, 2, 7, 0, 36, 2, 67, 0, 37, 2, 30, 0, 11, 0, 7, 0, 38, 2, + 7, 0, 39, 2, 7, 0, 40, 2, 7, 0,255, 0, 2, 0, 54, 0, 0, 0, 41, 2, 0, 0, 42, 2, 0, 0, 43, 2, 0, 0, 44, 2, + 0, 0, 45, 2, 0, 0, 46, 2, 29, 0, 7, 0, 7, 0, 47, 2, 7, 0, 39, 2, 7, 0, 40, 2, 2, 0, 43, 2, 2, 0, 46, 2, + 7, 0,255, 0, 7, 0, 27, 0, 70, 0, 21, 0, 70, 0, 0, 0, 70, 0, 1, 0, 2, 0, 16, 0, 2, 0, 48, 2, 2, 0, 46, 2, + 2, 0, 18, 0, 2, 0, 49, 2, 2, 0, 50, 2, 2, 0, 51, 2, 2, 0, 52, 2, 2, 0, 53, 2, 2, 0, 54, 2, 2, 0, 55, 2, + 2, 0, 56, 2, 7, 0, 57, 2, 7, 0, 58, 2, 29, 0, 48, 0, 30, 0, 49, 0, 2, 0, 59, 2, 2, 0, 60, 2, 4, 0, 61, 2, + 71, 0, 5, 0, 2, 0, 62, 2, 2, 0, 48, 2, 0, 0, 18, 0, 0, 0, 27, 0, 2, 0, 30, 0, 72, 0, 4, 0, 7, 0, 5, 0, + 7, 0, 6, 0, 7, 0, 63, 2, 7, 0, 64, 2, 73, 0, 4, 0, 14, 0, 65, 2, 74, 0, 66, 2, 4, 0, 67, 2, 0, 0, 94, 0, + 75, 0, 68, 0, 22, 0, 32, 0, 34, 0, 75, 0, 68, 0, 16, 2, 14, 0, 68, 2, 14, 0, 29, 2, 73, 0, 69, 2, 27, 0, 70, 2, + 27, 0, 71, 2, 27, 0, 72, 2, 31, 0, 80, 0, 76, 0, 73, 2, 33, 0, 74, 2, 63, 0, 31, 2, 14, 0, 75, 2, 7, 0, 77, 1, + 7, 0,176, 0, 7, 0, 78, 1, 2, 0, 16, 0, 2, 0,178, 0, 2, 0, 76, 2, 2, 0, 77, 2, 7, 0, 78, 2, 7, 0, 79, 2, + 4, 0, 80, 2, 2, 0, 27, 0, 2, 0, 33, 2, 2, 0, 18, 0, 2, 0, 81, 2, 7, 0, 82, 2, 7, 0, 83, 2, 7, 0, 84, 2, + 2, 0, 51, 2, 2, 0, 52, 2, 2, 0, 85, 2, 2, 0, 86, 2, 4, 0, 87, 2, 11, 0, 88, 2, 2, 0, 22, 0, 2, 0, 97, 0, + 2, 0, 66, 0, 2, 0, 89, 2, 7, 0, 90, 2, 7, 0, 91, 2, 7, 0, 92, 2, 7, 0, 93, 2, 7, 0, 94, 2, 7, 0, 95, 2, + 7, 0, 96, 2, 7, 0, 97, 2, 7, 0, 98, 2, 7, 0, 99, 2, 0, 0,100, 2, 77, 0,101, 2, 78, 0,102, 2, 0, 0,103, 2, + 65, 0,104, 2, 65, 0,105, 2, 65, 0,106, 2, 65, 0,107, 2, 4, 0,108, 2, 7, 0, 84, 0, 4, 0,109, 2, 4, 0,110, 2, + 72, 0,111, 2, 4, 0,112, 2, 4, 0,113, 2, 71, 0,114, 2, 71, 0,115, 2, 79, 0, 47, 0, 22, 0, 32, 0, 34, 0, 75, 0, + 68, 0, 16, 2, 31, 0, 80, 0, 33, 0, 74, 2, 63, 0, 31, 2, 80, 0,116, 2, 81, 0,117, 2, 82, 0,118, 2, 83, 0,119, 2, + 84, 0,120, 2, 85, 0,121, 2, 86, 0,122, 2, 87, 0,123, 2, 88, 0,124, 2, 89, 0,125, 2, 90, 0,126, 2, 91, 0,127, 2, + 92, 0,128, 2, 93, 0,129, 2, 79, 0,130, 2, 94, 0,131, 2, 95, 0,132, 2, 95, 0,133, 2, 95, 0,134, 2, 95, 0,135, 2, + 95, 0,136, 2, 4, 0, 53, 0, 4, 0,137, 2, 4, 0,138, 2, 4, 0,139, 2, 4, 0,140, 2, 4, 0,141, 2, 4, 0,142, 2, + 7, 0, 77, 1, 7, 0,176, 0, 7, 0, 78, 1, 2, 0,178, 0, 2, 0, 76, 2, 2, 0,143, 2, 2, 0, 18, 0, 2, 0,144, 2, + 2, 0,145, 2, 0, 0,146, 2, 0, 0,147, 2, 2, 0, 33, 2, 96, 0,148, 2, 88, 0, 8, 0, 11, 0,149, 2, 7, 0,150, 2, + 4, 0,151, 2, 0, 0, 18, 0, 0, 0,152, 2, 2, 0, 87, 1, 2, 0,153, 2, 2, 0,154, 2, 86, 0, 7, 0, 4, 0,155, 2, + 4, 0,156, 2, 4, 0,157, 2, 4, 0,158, 2, 2, 0, 48, 2, 0, 0,159, 2, 0, 0, 18, 0, 90, 0, 5, 0, 4, 0,155, 2, + 4, 0,156, 2, 0, 0,160, 2, 0, 0,161, 2, 2, 0, 18, 0, 97, 0, 2, 0, 4, 0,162, 2, 7, 0, 40, 2, 91, 0, 3, 0, + 97, 0,163, 2, 4, 0,164, 2, 4, 0, 18, 0, 89, 0, 4, 0, 7, 0,165, 2, 2, 0,166, 2, 0, 0, 18, 0, 0, 0,161, 2, + 92, 0, 4, 0, 0, 0,240, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0,187, 0, 81, 0, 5, 0, 4, 0,167, 2, 4, 0,141, 2, + 2, 0, 48, 2, 0, 0, 18, 0, 0, 0, 27, 0, 83, 0, 2, 0, 4, 0,168, 2, 4, 0,169, 2, 82, 0, 6, 0, 42, 0,149, 2, + 0, 0, 18, 0, 0, 0,152, 2, 2, 0, 87, 1, 2, 0,153, 2, 2, 0,154, 2, 84, 0, 2, 0, 7, 0,170, 2, 4, 0, 18, 0, + 85, 0, 4, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0,187, 0, 0, 0,240, 0, 93, 0, 1, 0, 7, 0,171, 2, 80, 0, 2, 0, + 4, 0, 14, 2, 4, 0, 16, 0, 87, 0, 7, 0, 7, 0,150, 2, 42, 0,149, 2, 0, 0, 18, 0, 0, 0,152, 2, 2, 0, 87, 1, + 2, 0,153, 2, 2, 0,154, 2, 98, 0, 1, 0, 7, 0,172, 2, 99, 0, 1, 0, 4, 0,173, 2,100, 0, 1, 0, 0, 0,174, 2, +101, 0, 1, 0, 7, 0,150, 2,102, 0, 1, 0, 7, 0,170, 2,103, 0, 4, 0, 4, 0,175, 2, 4, 0,176, 2, 7, 0,177, 2, + 4, 0,178, 2,104, 0, 4, 0, 7, 0,240, 0, 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0,105, 0, 1, 0,104, 0,151, 2, +106, 0, 5, 0, 4, 0,179, 2, 4, 0,180, 2, 0, 0, 18, 0, 0, 0, 48, 2, 0, 0,181, 2,107, 0, 2, 0, 4, 0,182, 2, + 4, 0,180, 2,108, 0, 10, 0,108, 0, 0, 0,108, 0, 1, 0,106, 0,183, 2,105, 0,184, 2,107, 0,185, 2, 4, 0, 53, 0, + 4, 0,138, 2, 4, 0,137, 2, 4, 0, 27, 0, 89, 0,186, 2, 96, 0, 14, 0, 14, 0,187, 2, 89, 0,186, 2, 0, 0,188, 2, + 0, 0,189, 2, 0, 0,190, 2, 0, 0,191, 2, 0, 0,192, 2, 0, 0,193, 2, 0, 0,194, 2, 0, 0, 18, 0, 95, 0,132, 2, + 95, 0,134, 2, 2, 0,195, 2, 0, 0,196, 2,109, 0, 1, 0, 4, 0,173, 2,110, 0, 9, 0,110, 0, 0, 0,110, 0, 1, 0, + 4, 0, 16, 0, 4, 0, 87, 1, 4, 0,197, 2, 4, 0, 27, 0, 0, 0, 19, 0, 41, 0,125, 0, 0, 0,198, 2,111, 0, 6, 0, +110, 0,199, 2, 47, 0,200, 2, 27, 0,201, 2, 0, 0,202, 2, 4, 0,203, 2, 4, 0,204, 2,112, 0, 7, 0,110, 0,199, 2, + 2, 0,205, 2, 2, 0,187, 2, 2, 0,206, 2, 2, 0, 92, 0, 11, 0,207, 2, 11, 0,208, 2,113, 0, 5, 0,110, 0,199, 2, + 27, 0,168, 0, 0, 0, 19, 0, 7, 0,209, 2, 0, 0, 94, 0,114, 0, 5, 0,110, 0,199, 2, 27, 0,168, 0, 0, 0, 19, 0, + 2, 0,210, 2, 0, 0,211, 2,115, 0, 5, 0,110, 0,199, 2, 7, 0, 90, 0, 7, 0,212, 2, 4, 0,213, 2, 4, 0,214, 2, +116, 0, 5, 0,110, 0,199, 2, 27, 0,215, 2, 0, 0, 72, 0, 4, 0, 87, 1, 4, 0, 18, 0,117, 0, 13, 0,110, 0,199, 2, + 27, 0,216, 2, 27, 0,217, 2, 27, 0,218, 2, 27, 0,219, 2, 7, 0,220, 2, 7, 0,221, 2, 7, 0,212, 2, 7, 0,222, 2, + 4, 0,223, 2, 4, 0,224, 2, 4, 0, 92, 0, 4, 0,225, 2,118, 0, 5, 0,110, 0,199, 2, 2, 0,226, 2, 2, 0, 18, 0, + 7, 0,227, 2, 27, 0,228, 2,119, 0, 3, 0,110, 0,199, 2, 7, 0,229, 2, 4, 0, 92, 0,120, 0, 10, 0,110, 0,199, 2, + 7, 0,230, 2, 4, 0,231, 2, 4, 0, 27, 0, 2, 0, 92, 0, 2, 0,232, 2, 2, 0,233, 2, 2, 0,234, 2, 7, 0,235, 2, + 0, 0,236, 2,121, 0, 3, 0,110, 0,199, 2, 7, 0, 27, 0, 4, 0, 16, 0,122, 0, 6, 0,110, 0,199, 2,123, 0,237, 2, +124, 0,238, 2,125, 0,239, 2, 7, 0,240, 2, 4, 0, 16, 0,126, 0, 11, 0,110, 0,199, 2, 47, 0,200, 2, 27, 0,201, 2, + 0, 0,202, 2, 4, 0,203, 2, 4, 0,204, 2, 7, 0,209, 2, 4, 0,241, 2, 0, 0,236, 2, 7, 0,242, 2, 4, 0, 27, 0, +127, 0, 12, 0,110, 0,199, 2, 27, 0,243, 2, 42, 0,244, 2, 4, 0, 92, 0, 4, 0,245, 2, 7, 0,246, 2, 7, 0,247, 2, + 7, 0,248, 2, 7, 0,249, 2, 0, 0,202, 2, 4, 0,203, 2, 4, 0, 27, 0,128, 0, 3, 0,110, 0,199, 2, 7, 0,250, 2, + 4, 0,251, 2,129, 0, 5, 0,110, 0,199, 2, 7, 0,252, 2, 0, 0,236, 2, 2, 0, 18, 0, 2, 0,253, 2,130, 0, 8, 0, +110, 0,199, 2, 27, 0,168, 0, 7, 0,252, 2, 7, 0,255, 0, 7, 0,108, 0, 0, 0,236, 2, 2, 0, 18, 0, 2, 0, 16, 0, +131, 0, 21, 0,110, 0,199, 2, 47, 0,200, 2, 27, 0,201, 2, 0, 0,202, 2, 4, 0,203, 2, 4, 0,204, 2, 27, 0,254, 2, + 0, 0,236, 2, 2, 0, 18, 0, 2, 0, 27, 0, 7, 0,255, 2, 7, 0, 0, 3, 7, 0, 1, 3, 7, 0, 82, 2, 7, 0, 2, 3, + 7, 0, 3, 3, 7, 0, 4, 3, 7, 0, 5, 3, 7, 0, 6, 3, 7, 0, 7, 3, 7, 0, 67, 0,132, 0, 7, 0,110, 0,199, 2, + 2, 0, 8, 3, 2, 0, 9, 3, 4, 0, 30, 0, 27, 0,168, 0, 7, 0, 10, 3, 0, 0,236, 2,133, 0, 10, 0,110, 0,199, 2, + 27, 0,168, 0, 0, 0, 11, 3, 7, 0, 12, 3, 7, 0, 13, 3, 7, 0, 5, 3, 4, 0, 14, 3, 4, 0, 15, 3, 7, 0, 16, 3, + 0, 0, 19, 0,134, 0, 1, 0,110, 0,199, 2,135, 0, 7, 0,110, 0,199, 2, 41, 0,125, 0,136, 0, 17, 3,137, 0, 18, 3, +138, 0, 19, 3,139, 0, 20, 3, 14, 0, 21, 3,140, 0, 13, 0,110, 0,199, 2, 89, 0, 22, 3, 89, 0, 23, 3, 89, 0, 24, 3, + 89, 0, 25, 3, 89, 0, 26, 3, 89, 0, 27, 3, 86, 0, 28, 3, 4, 0, 29, 3, 4, 0, 30, 3, 7, 0, 31, 3, 7, 0, 32, 3, +141, 0, 33, 3,142, 0, 7, 0,110, 0,199, 2, 89, 0, 22, 3, 89, 0, 34, 3,143, 0, 35, 3,144, 0, 33, 3, 4, 0, 36, 3, + 4, 0, 29, 3,145, 0, 4, 0,110, 0,199, 2, 27, 0,168, 0, 4, 0, 37, 3, 4, 0, 27, 0,146, 0, 2, 0, 4, 0, 38, 3, + 7, 0, 40, 2,147, 0, 2, 0, 4, 0,128, 0, 4, 0, 39, 3,148, 0, 24, 0,110, 0,199, 2, 27, 0,168, 0, 0, 0,236, 2, + 2, 0, 40, 3, 2, 0, 18, 0, 2, 0, 87, 1, 2, 0, 27, 0,146, 0, 41, 3, 4, 0, 42, 3, 7, 0, 43, 3, 4, 0, 53, 0, + 4, 0, 44, 3,147, 0, 45, 3,146, 0, 46, 3, 4, 0, 47, 3, 4, 0, 48, 3, 4, 0, 49, 3, 4, 0, 39, 3, 7, 0, 50, 3, + 7, 0, 51, 3, 7, 0, 52, 3, 7, 0, 53, 3, 7, 0, 54, 3, 11, 0, 55, 3,149, 0, 8, 0,110, 0,199, 2,150, 0, 56, 3, +143, 0, 35, 3, 4, 0, 57, 3, 4, 0, 58, 3, 4, 0, 59, 3, 2, 0, 18, 0, 2, 0, 56, 0,151, 0, 8, 0,110, 0,199, 2, + 27, 0, 44, 0, 2, 0, 3, 1, 2, 0, 18, 0, 2, 0,226, 2, 2, 0, 56, 0, 7, 0, 60, 3, 7, 0, 61, 3,152, 0, 6, 0, +110, 0,199, 2, 4, 0, 62, 3, 2, 0, 18, 0, 2, 0, 63, 3, 7, 0, 64, 3, 0, 0,170, 0,153, 0, 8, 0,110, 0,199, 2, + 0, 0, 65, 3, 0, 0, 66, 3, 0, 0,193, 2, 0, 0, 67, 3, 0, 0, 68, 3, 0, 0, 92, 0, 0, 0,181, 2,154, 0, 3, 0, +110, 0,199, 2,155, 0, 69, 3,139, 0, 20, 3,156, 0, 10, 0,110, 0,199, 2, 27, 0, 70, 3, 27, 0, 71, 3, 0, 0, 72, 3, + 7, 0, 73, 3, 2, 0, 74, 3, 2, 0, 75, 3, 0, 0, 76, 3, 0, 0, 77, 3, 0, 0,211, 2,157, 0, 9, 0,110, 0,199, 2, + 27, 0, 78, 3, 0, 0, 72, 3, 7, 0, 79, 3, 7, 0, 80, 3, 0, 0, 87, 1, 0, 0,226, 2, 0, 0, 81, 3, 0, 0, 27, 0, +158, 0, 1, 0,110, 0,199, 2,159, 0, 11, 0,110, 0,199, 2, 0, 0,236, 2, 7, 0,128, 0, 7, 0, 82, 3, 7, 0, 83, 3, + 7, 0, 84, 3, 7, 0, 85, 3, 7, 0, 86, 3, 4, 0, 18, 0, 2, 0, 87, 3, 2, 0, 88, 3,160, 0, 9, 0,110, 0,199, 2, + 27, 0, 89, 3, 4, 0, 90, 3, 4, 0, 91, 3, 4, 0, 92, 3, 7, 0, 93, 3, 7, 0, 94, 3, 2, 0,226, 2, 2, 0, 18, 0, +161, 0, 29, 0,110, 0,199, 2,162, 0, 95, 3,163, 0, 96, 3, 4, 0, 97, 3, 4, 0, 98, 3, 7, 0, 99, 3, 7, 0, 4, 3, + 7, 0,100, 3, 7, 0,250, 0, 7, 0,101, 3, 7, 0,102, 3, 7, 0,103, 3, 7, 0,104, 3, 7, 0,105, 3, 7, 0,240, 2, + 4, 0,106, 3, 4, 0,107, 3, 0, 0,108, 3, 0, 0,109, 3, 0, 0,110, 3, 0, 0,111, 3, 0, 0, 18, 0, 0, 0,112, 3, + 2, 0,113, 3, 2, 0,114, 3, 4, 0,214, 2, 7, 0,108, 0, 7, 0,115, 3, 4, 0, 27, 0,164, 0, 15, 0,110, 0,199, 2, + 47, 0,200, 2, 27, 0,201, 2, 0, 0,202, 2, 4, 0,203, 2, 4, 0,204, 2, 27, 0,116, 3, 27, 0,117, 3, 54, 0,100, 1, + 0, 0,236, 2, 7, 0,209, 2, 7, 0,118, 3, 0, 0, 18, 0, 0, 0,253, 0, 0, 0,211, 2,165, 0, 16, 0,110, 0,199, 2, + 0, 0,236, 2, 2, 0,119, 3, 2, 0,253, 0, 7, 0,120, 3, 54, 0,121, 3, 7, 0,122, 3, 7, 0,123, 3, 7, 0,124, 3, + 0, 0,125, 3, 4, 0,126, 3, 47, 0,127, 3, 27, 0,128, 3, 4, 0,129, 3, 0, 0,130, 3, 4, 0,131, 3,166, 0, 16, 0, +110, 0,199, 2, 0, 0,132, 3, 0, 0,133, 3, 7, 0,134, 3, 7, 0,135, 3, 0, 0,136, 3, 0, 0,137, 3, 0, 0,138, 3, + 7, 0,124, 3, 0, 0,125, 3, 4, 0,126, 3, 47, 0,127, 3, 27, 0,128, 3, 4, 0,129, 3, 0, 0,130, 3, 4, 0,131, 3, +167, 0, 16, 0,110, 0,199, 2, 0, 0,236, 2, 4, 0,139, 3, 4, 0,140, 3, 27, 0,141, 3, 7, 0,124, 3, 0, 0,125, 3, + 4, 0,126, 3, 47, 0,127, 3, 27, 0,128, 3, 4, 0,129, 3, 0, 0,130, 3, 7, 0,142, 3, 7, 0,143, 3, 2, 0,253, 0, + 2, 0,144, 3,168, 0, 5, 0,110, 0,199, 2,169, 0,145, 3,170, 0,146, 3, 4, 0, 16, 0, 4, 0, 27, 0,171, 0, 8, 0, +110, 0,199, 2, 7, 0,147, 3, 7, 0,148, 3, 7, 0,149, 3, 0, 0,250, 0, 0, 0, 18, 0, 0, 0, 87, 1, 0, 0, 27, 0, +172, 0, 3, 0,173, 0,150, 3, 4, 0, 67, 2, 0, 0, 94, 0,173, 0, 29, 0, 22, 0, 32, 0, 34, 0, 75, 0, 2, 0, 49, 2, + 2, 0, 50, 2, 2, 0,151, 3, 2, 0, 18, 0, 2, 0,152, 3, 2, 0,153, 3, 2, 0,154, 3, 2, 0, 30, 0, 0, 0,155, 3, + 0, 0,156, 3, 0, 0,157, 3, 0, 0,247, 1, 4, 0, 27, 0, 7, 0,158, 3, 7, 0,159, 3, 7, 0,160, 3, 7, 0,161, 3, + 7, 0,162, 3, 7, 0,163, 3, 29, 0,164, 3, 31, 0, 80, 0, 33, 0, 74, 2, 91, 0,127, 2, 0, 0, 72, 0, 7, 0,165, 3, + 7, 0,166, 3,172, 0,167, 3,174, 0, 5, 0,174, 0, 0, 0,174, 0, 1, 0, 0, 0, 19, 0, 0, 0, 18, 0, 0, 0,124, 0, + 68, 0, 3, 0, 7, 0,168, 3, 4, 0, 18, 0, 4, 0, 27, 0, 27, 0,128, 0, 22, 0, 32, 0, 34, 0, 75, 0,175, 0,169, 3, + 2, 0, 16, 0, 2, 0,170, 3, 4, 0,171, 3, 4, 0,172, 3, 4, 0,173, 3, 0, 0,174, 3, 27, 0, 38, 0, 27, 0,175, 3, + 27, 0,176, 3, 27, 0,177, 3, 27, 0,178, 3, 31, 0, 80, 0, 68, 0, 16, 2,176, 0,179, 3,176, 0,180, 3,177, 0,181, 3, + 11, 0, 2, 0,178, 0,182, 3,179, 0,183, 3,180, 0,184, 3, 14, 0,185, 3, 14, 0,186, 3, 14, 0, 29, 2, 14, 0,187, 3, + 14, 0,188, 3, 4, 0, 87, 1, 4, 0,189, 3, 63, 0, 31, 2, 0, 0,190, 3, 4, 0, 33, 2, 4, 0,191, 3, 7, 0, 77, 1, + 7, 0,192, 3, 7, 0,193, 3, 7, 0,176, 0, 7, 0,194, 3, 7, 0,195, 3, 7, 0, 78, 1, 7, 0,196, 3, 7, 0, 19, 2, + 7, 0,197, 3, 7, 0,198, 3, 7, 0,199, 3, 7, 0,200, 3, 7, 0,201, 3, 7, 0,202, 3, 7, 0, 12, 3, 7, 0,203, 3, + 7, 0,244, 0, 7, 0,204, 3, 4, 0,205, 3, 4, 0,206, 3, 2, 0, 18, 0, 2, 0,207, 3, 2, 0,208, 3, 2, 0,209, 3, + 2, 0,210, 3, 2, 0,211, 3, 2, 0,212, 3, 2, 0,213, 3, 2, 0,214, 3, 0, 0,215, 3, 0, 0,216, 3, 4, 0,217, 3, + 4, 0,218, 3, 4, 0,219, 3, 4, 0,220, 3, 7, 0,221, 3, 7, 0, 84, 0, 7, 0,222, 3, 7, 0,223, 3, 7, 0,224, 3, + 7, 0,225, 3, 7, 0,226, 3, 7, 0,220, 0, 7, 0,227, 3, 7, 0,228, 3, 7, 0,229, 3, 7, 0,230, 3, 7, 0,231, 3, + 2, 0,232, 3, 0, 0,233, 3, 0, 0,234, 3, 0, 0,235, 3, 0, 0,236, 3, 0, 0,110, 0, 0, 0,237, 3, 7, 0,238, 3, + 7, 0,239, 3, 14, 0,240, 3, 14, 0,241, 3, 14, 0,242, 3, 14, 0,243, 3, 7, 0,244, 3, 2, 0, 14, 2, 2, 0,245, 3, + 7, 0,151, 2, 4, 0,246, 3, 4, 0,247, 3,181, 0,248, 3, 2, 0,249, 3, 2, 0,251, 0, 7, 0,250, 3, 14, 0,251, 3, + 14, 0,252, 3, 14, 0,253, 3, 14, 0,254, 3,182, 0, 73, 1,183, 0,255, 3, 64, 0, 0, 4, 0, 0, 1, 4, 0, 0, 2, 4, + 2, 0, 67, 2, 7, 0,143, 2,155, 0, 3, 4,143, 0, 4, 4,143, 0, 5, 4, 10, 0, 6, 4, 10, 0, 7, 4, 4, 0, 8, 4, + 4, 0, 9, 4, 14, 0, 10, 4, 14, 0, 11, 4, 14, 0, 12, 4, 7, 0, 13, 4,184, 0, 14, 0,184, 0, 0, 0,184, 0, 1, 0, + 27, 0, 38, 0, 7, 0, 12, 3, 7, 0, 79, 1, 7, 0, 13, 3, 7, 0, 5, 3, 0, 0, 19, 0, 4, 0, 14, 3, 4, 0, 15, 3, + 4, 0, 14, 4, 2, 0, 16, 0, 2, 0, 15, 4, 7, 0, 16, 3,185, 0, 12, 0,185, 0, 0, 0,185, 0, 1, 0, 27, 0, 44, 0, + 4, 0, 16, 4, 4, 0, 14, 2, 7, 0, 79, 1, 7, 0, 17, 4, 7, 0, 18, 4, 7, 0,170, 2, 2, 0, 16, 0, 0, 0, 19, 4, + 0, 0, 20, 4,182, 0, 40, 0, 4, 0, 18, 0, 2, 0, 21, 4, 2, 0, 22, 4, 2, 0, 5, 3, 2, 0, 23, 4, 2, 0, 24, 4, + 2, 0, 25, 4, 2, 0, 26, 4, 2, 0, 27, 4, 7, 0, 28, 4, 7, 0, 29, 4, 7, 0, 30, 4, 7, 0, 31, 4, 7, 0, 32, 4, + 7, 0, 33, 4, 7, 0, 34, 4, 7, 0, 35, 4, 7, 0, 36, 4, 7, 0, 37, 4, 7, 0, 38, 4, 7, 0, 39, 4, 7, 0, 40, 4, + 7, 0, 41, 4, 7, 0, 42, 4, 7, 0, 43, 4, 7, 0, 44, 4, 7, 0, 45, 4, 7, 0, 46, 4, 7, 0, 47, 4, 7, 0, 48, 4, + 7, 0, 49, 4, 7, 0, 50, 4, 7, 0, 51, 4, 7, 0, 52, 4, 7, 0, 53, 4, 7, 0, 54, 4, 47, 0,169, 0,186, 0, 55, 4, + 7, 0, 56, 4, 4, 0,214, 2,187, 0, 5, 0, 64, 0,250, 1, 7, 0, 57, 4, 7, 0, 58, 4, 2, 0, 18, 0, 2, 0, 59, 4, +188, 0, 5, 0,188, 0, 0, 0,188, 0, 1, 0, 4, 0, 16, 0, 4, 0, 60, 4, 11, 0, 2, 0,189, 0, 9, 0,189, 0, 0, 0, +189, 0, 1, 0, 4, 0, 61, 4, 4, 0, 62, 4, 4, 0, 63, 4, 4, 0, 18, 0, 11, 0, 64, 4, 11, 0, 65, 4, 14, 0, 66, 4, +139, 0, 23, 0,139, 0, 0, 0,139, 0, 1, 0, 4, 0, 18, 0, 4, 0, 67, 4, 4, 0, 68, 4, 4, 0, 69, 4, 4, 0, 70, 4, + 4, 0, 71, 4, 4, 0, 72, 4, 4, 0, 73, 4, 4, 0, 27, 0, 4, 0, 62, 4, 4, 0, 14, 2, 2, 0, 74, 4, 2, 0, 56, 0, + 0, 0, 19, 0, 0, 0, 75, 4, 0, 0, 76, 4, 0, 0, 77, 4, 0, 0, 78, 4, 14, 0, 79, 4,190, 0, 80, 4, 11, 0, 81, 4, +191, 0, 1, 0, 7, 0, 47, 2,181, 0, 30, 0, 4, 0, 18, 0, 7, 0, 82, 4, 7, 0, 83, 4, 7, 0, 84, 4, 4, 0, 85, 4, + 4, 0, 86, 4, 4, 0, 87, 4, 4, 0, 88, 4, 7, 0, 89, 4, 7, 0, 90, 4, 7, 0, 91, 4, 7, 0, 92, 4, 7, 0, 93, 4, + 7, 0, 94, 4, 7, 0, 95, 4, 7, 0, 96, 4, 7, 0, 97, 4, 7, 0, 98, 4, 7, 0, 99, 4, 7, 0,100, 4, 7, 0,101, 4, + 7, 0,102, 4, 7, 0,103, 4, 7, 0,104, 4, 7, 0,105, 4, 7, 0,106, 4, 4, 0,107, 4, 4, 0,108, 4, 7, 0,109, 4, + 7, 0,227, 3,183, 0, 54, 0, 4, 0, 62, 4, 4, 0,110, 4,192, 0,111, 4,193, 0,112, 4, 0, 0, 27, 0, 0, 0,113, 4, + 2, 0,114, 4, 7, 0,115, 4, 0, 0,116, 4, 7, 0,117, 4, 7, 0,118, 4, 7, 0,119, 4, 7, 0,120, 4, 7, 0,121, 4, + 7, 0,122, 4, 7, 0,123, 4, 7, 0,124, 4, 7, 0,125, 4, 2, 0,126, 4, 0, 0,127, 4, 2, 0,128, 4, 7, 0,129, 4, + 7, 0,130, 4, 0, 0,131, 4, 4, 0,129, 0, 4, 0,132, 4, 4, 0,133, 4, 2, 0,134, 4, 2, 0,135, 4,191, 0,136, 4, + 4, 0,137, 4, 4, 0, 82, 0, 7, 0,138, 4, 7, 0,139, 4, 7, 0,140, 4, 7, 0,141, 4, 2, 0,142, 4, 2, 0,143, 4, + 2, 0,144, 4, 2, 0,145, 4, 2, 0,146, 4, 2, 0,147, 4, 2, 0,148, 4, 2, 0,149, 4,194, 0,150, 4, 7, 0,151, 4, + 7, 0,152, 4,139, 0,153, 4, 14, 0, 21, 3,187, 0,154, 4, 7, 0,155, 4, 7, 0,156, 4, 7, 0,157, 4, 4, 0,158, 4, +195, 0, 1, 0, 7, 0,159, 4,155, 0, 52, 0,154, 0,160, 4, 2, 0, 16, 0, 2, 0,161, 4, 2, 0,162, 4, 2, 0,163, 4, + 7, 0,164, 4, 2, 0,165, 4, 2, 0,166, 4, 7, 0,167, 4, 2, 0,168, 4, 2, 0,169, 4, 7, 0,170, 4, 7, 0,171, 4, + 7, 0,172, 4, 4, 0,173, 4, 4, 0,174, 4, 4, 0,175, 4, 4, 0, 27, 0, 7, 0,176, 4, 4, 0,177, 4, 7, 0,178, 4, + 7, 0,179, 4, 7, 0,180, 4, 79, 0,181, 4, 79, 0,182, 4, 0, 0,183, 4, 7, 0,184, 4, 7, 0,185, 4, 31, 0, 80, 0, + 2, 0,186, 4, 0, 0,187, 4, 0, 0,188, 4, 7, 0,189, 4, 4, 0,190, 4, 7, 0,191, 4, 7, 0,192, 4, 4, 0,193, 4, + 4, 0, 18, 0, 7, 0,194, 4, 7, 0,195, 4, 7, 0,196, 4,195, 0,197, 4, 4, 0, 53, 0, 7, 0,198, 4, 7, 0,199, 4, + 7, 0,200, 4, 7, 0,201, 4, 7, 0,202, 4, 7, 0,203, 4, 7, 0,204, 4, 4, 0,205, 4, 7, 0,206, 4,196, 0, 78, 0, + 22, 0, 32, 0, 34, 0, 75, 0, 2, 0,179, 0, 2, 0, 88, 1, 2, 0,122, 1, 2, 0,207, 4, 7, 0,208, 4, 7, 0,209, 4, + 7, 0,210, 4, 7, 0,211, 4, 7, 0,212, 4, 7, 0,213, 4, 7, 0,170, 1, 7, 0,172, 1, 7, 0,171, 1, 7, 0, 30, 0, + 4, 0,214, 4, 7, 0,215, 4, 7, 0,216, 4, 7, 0,217, 4, 7, 0,218, 4, 7, 0,219, 4, 7, 0,220, 4, 7, 0,221, 4, + 2, 0,222, 4, 2, 0, 87, 1, 2, 0,223, 4, 2, 0,224, 4, 2, 0,225, 4, 2, 0,226, 4, 2, 0,227, 4, 2, 0,228, 4, + 7, 0,229, 4, 7, 0,230, 4, 7, 0,231, 4, 7, 0,232, 4, 7, 0,233, 4, 7, 0,234, 4, 7, 0,235, 4, 7, 0,236, 4, + 7, 0,237, 4, 7, 0,238, 4, 7, 0,239, 4, 7, 0,240, 4, 2, 0,241, 4, 2, 0,242, 4, 2, 0,243, 4, 2, 0,244, 4, + 7, 0,245, 4, 7, 0,246, 4, 7, 0,247, 4, 7, 0,248, 4, 2, 0,249, 4, 2, 0,250, 4, 2, 0,251, 4, 2, 0,252, 4, + 7, 0,253, 4, 7, 0,254, 4, 7, 0,255, 4, 7, 0, 0, 5, 7, 0, 1, 5, 7, 0, 2, 5, 7, 0, 3, 5, 2, 0, 4, 5, + 2, 0, 5, 5, 2, 0, 6, 5, 2, 0, 7, 5, 2, 0, 8, 5, 2, 0, 18, 0, 7, 0, 9, 5, 7, 0, 10, 5, 31, 0, 80, 0, + 46, 0,140, 1, 2, 0,141, 1, 2, 0, 76, 1, 2, 0,181, 2, 25, 0,154, 0, 57, 0, 70, 1,197, 0, 8, 0,197, 0, 0, 0, +197, 0, 1, 0, 4, 0,205, 3, 4, 0, 11, 5, 4, 0, 18, 0, 2, 0, 12, 5, 2, 0, 13, 5, 27, 0,168, 0,198, 0, 13, 0, + 11, 0, 14, 5, 11, 0, 15, 5, 4, 0, 16, 5, 4, 0, 17, 5, 4, 0, 18, 5, 4, 0, 19, 5, 4, 0, 20, 5, 4, 0, 21, 5, + 4, 0, 22, 5, 4, 0, 23, 5, 4, 0, 24, 5, 4, 0, 27, 0, 0, 0, 25, 5,199, 0, 5, 0, 11, 0, 26, 5, 11, 0, 27, 5, + 4, 0, 28, 5, 4, 0, 30, 0, 0, 0, 29, 5,200, 0, 17, 0, 4, 0, 30, 5, 4, 0, 31, 5, 4, 0, 32, 5, 4, 0, 33, 5, + 4, 0, 34, 5, 4, 0, 35, 5, 4, 0, 36, 5, 4, 0, 37, 5, 4, 0, 38, 5, 4, 0, 39, 5, 4, 0, 40, 5, 4, 0, 41, 5, + 2, 0, 42, 5, 2, 0, 43, 5, 4, 0, 44, 5, 4, 0, 45, 5, 4, 0, 67, 0,201, 0, 17, 0, 4, 0, 16, 0, 4, 0, 32, 5, + 4, 0, 46, 5, 4, 0, 47, 5, 4, 0, 48, 5, 4, 0, 49, 5, 4, 0, 50, 5, 4, 0, 51, 5, 7, 0, 52, 5, 4, 0, 53, 5, + 4, 0, 92, 0, 4, 0, 54, 5, 4, 0, 55, 5, 4, 0, 56, 5, 4, 0, 57, 5, 4, 0, 58, 5, 21, 0, 31, 0,202, 0, 9, 0, + 4, 0, 59, 5, 7, 0, 60, 5, 7, 0, 61, 5, 7, 0, 62, 5, 4, 0, 63, 5, 2, 0, 18, 0, 2, 0, 27, 0, 7, 0, 84, 4, + 7, 0, 30, 0,203, 0, 11, 0,203, 0, 0, 0,203, 0, 1, 0, 0, 0, 19, 0, 63, 0, 64, 5, 64, 0, 65, 5, 4, 0,205, 3, + 4, 0, 66, 5, 4, 0, 67, 5, 4, 0, 27, 0, 4, 0, 68, 5, 4, 0, 69, 5,204, 0, 13, 0, 0, 0, 70, 5, 0, 0,250, 0, + 0, 0, 71, 5, 0, 0, 18, 0, 0, 0, 72, 5, 0, 0, 73, 5, 0, 0, 74, 5, 0, 0, 75, 5, 2, 0, 76, 5, 2, 0, 77, 5, + 7, 0, 78, 5, 0, 0, 79, 5, 0, 0,124, 0,205, 0,106, 0,204, 0, 80, 5,198, 0, 81, 5,199, 0, 82, 5,200, 0, 83, 5, +201, 0, 84, 5, 4, 0, 36, 3, 4, 0,129, 0, 4, 0,132, 4, 7, 0, 85, 5, 4, 0, 86, 5, 4, 0, 87, 5, 4, 0, 88, 5, + 4, 0, 89, 5, 2, 0, 18, 0, 2, 0, 90, 5, 7, 0, 91, 5, 7, 0, 92, 5, 7, 0, 93, 5, 7, 0, 94, 5, 7, 0, 95, 5, + 2, 0, 96, 5, 2, 0, 97, 5, 2, 0, 98, 5, 2, 0, 99, 5, 2, 0,250, 0, 2, 0,100, 5, 4, 0,101, 5, 2, 0,102, 5, + 2, 0,103, 5, 2, 0,109, 1, 2, 0,108, 0, 2, 0,104, 5, 2, 0,105, 5, 2, 0,106, 5, 2, 0,107, 5, 2, 0,108, 5, + 2, 0, 71, 5, 2, 0, 70, 5, 2, 0,109, 5, 2, 0, 72, 5, 2, 0,110, 5, 4, 0,111, 5, 4, 0, 87, 1, 4, 0,112, 5, + 2, 0,113, 5, 2, 0, 67, 0, 2, 0,114, 5, 2, 0,115, 5, 2, 0,116, 5, 2, 0,117, 5, 2, 0,118, 5, 2, 0,119, 5, + 19, 0,120, 5, 19, 0,121, 5, 18, 0,122, 5, 14, 0,123, 5, 2, 0,124, 5, 2, 0,125, 5, 7, 0,126, 5, 7, 0,127, 5, + 7, 0,128, 5, 7, 0,129, 5, 4, 0,130, 5, 7, 0,131, 5, 7, 0,132, 5, 7, 0,133, 5, 7, 0,134, 5, 2, 0,135, 5, + 2, 0,136, 5, 2, 0,137, 5, 2, 0,138, 5, 2, 0,139, 5, 2, 0,140, 5, 7, 0,141, 5, 7, 0,142, 5, 7, 0,143, 5, + 0, 0,144, 5, 4, 0,145, 5, 2, 0,146, 5, 2, 0,247, 1, 0, 0,147, 5, 7, 0,148, 5, 7, 0,149, 5, 0, 0,150, 5, + 0, 0,151, 5, 0, 0,152, 5, 0, 0,153, 5, 4, 0,154, 5, 2, 0,155, 5, 2, 0,156, 5, 7, 0,157, 5, 7, 0,158, 5, + 2, 0,159, 5, 2, 0,160, 5, 7, 0,161, 5, 2, 0,162, 5, 2, 0,163, 5, 4, 0,164, 5, 2, 0,165, 5, 2, 0,166, 5, + 2, 0,167, 5, 2, 0,168, 5, 7, 0,169, 5, 7, 0, 30, 0, 37, 0,170, 5, 0, 0,171, 5,206, 0, 9, 0,206, 0, 0, 0, +206, 0, 1, 0, 0, 0,172, 5, 2, 0,173, 5, 2, 0,174, 5, 2, 0,175, 5, 2, 0, 67, 0, 7, 0,176, 5, 7, 0, 30, 0, +207, 0, 7, 0, 2, 0,231, 2, 2, 0, 87, 1, 2, 0, 94, 3, 2, 0,177, 5, 7, 0,178, 5, 7, 0, 30, 0, 37, 0,179, 5, +208, 0, 5, 0, 7, 0,180, 5, 0, 0, 16, 0, 0, 0, 67, 0, 0, 0, 30, 0, 0, 0,247, 1,209, 0, 15, 0, 7, 0,181, 5, + 7, 0,182, 5, 7, 0,183, 5, 7, 0,184, 5, 7, 0,185, 5, 7, 0,186, 5, 7, 0,187, 5, 7, 0,188, 5, 7, 0,189, 5, + 7, 0,190, 5, 4, 0,191, 5, 7, 0,192, 5, 7, 0,193, 5, 2, 0, 67, 0, 2, 0, 30, 0,210, 0, 32, 0,208, 0,194, 5, + 2, 0,195, 5, 2, 0, 97, 5, 2, 0, 98, 5, 2, 0, 99, 5, 2, 0,250, 0, 2, 0,100, 5, 2, 0,196, 5, 2, 0,197, 5, + 2, 0,198, 5, 2, 0,199, 5,207, 0,200, 5, 2, 0,201, 5, 2, 0,102, 5, 7, 0,202, 5,209, 0,203, 5, 7, 0,220, 4, + 7, 0,221, 4, 4, 0, 18, 0, 2, 0, 87, 1, 2, 0,204, 5, 2, 0,223, 4, 2, 0,224, 4, 2, 0,205, 5, 2, 0, 27, 0, + 2, 0,225, 4, 2, 0,226, 4, 2, 0,227, 4, 2, 0,228, 4, 2, 0,206, 5, 2, 0, 67, 0, 7, 0,207, 5,211, 0, 6, 0, +211, 0, 0, 0,211, 0, 1, 0, 4, 0, 61, 4, 0, 0, 19, 0, 4, 0, 18, 0, 27, 0,208, 5,212, 0, 4, 0,213, 0,146, 3, + 11, 0,209, 5, 0, 0,210, 5, 4, 0, 92, 0,214, 0, 8, 0,212, 0,211, 5, 2, 0, 18, 0, 2, 0, 27, 0, 2, 0,212, 5, + 2, 0,213, 5, 2, 0,214, 5, 4, 0, 67, 0, 11, 0,215, 5,215, 0, 6, 0, 2, 0,108, 0, 2, 0, 67, 4, 2, 0,216, 5, + 2, 0,225, 2, 4, 0, 18, 0, 7, 0,209, 2,216, 0, 14, 0, 2, 0, 18, 0, 2, 0,217, 5, 2, 0,218, 5, 2, 0,219, 5, +215, 0,220, 5, 11, 0,215, 5, 7, 0,221, 5, 7, 0, 56, 0, 4, 0,222, 5, 4, 0,223, 5, 4, 0,224, 5, 4, 0,225, 5, + 41, 0,125, 0, 27, 0,168, 0,217, 0, 14, 0,212, 0,211, 5, 4, 0, 92, 0, 4, 0,226, 5, 7, 0,227, 5, 7, 0,228, 5, + 7, 0,229, 5, 4, 0,230, 5, 4, 0,231, 5, 7, 0,232, 5, 7, 0,233, 5, 4, 0,234, 5, 7, 0,235, 5, 7, 0,236, 5, + 4, 0, 27, 0,218, 0, 1, 0,212, 0,211, 5,219, 0, 7, 0,212, 0,211, 5, 2, 0, 18, 0, 2, 0, 27, 0, 4, 0, 37, 0, + 4, 0,237, 5, 91, 0,238, 5, 11, 0,215, 5,220, 0, 5, 0,220, 0, 0, 0,220, 0, 1, 0, 0, 0, 19, 0, 7, 0,239, 5, + 4, 0, 27, 0,221, 0, 4, 0, 4, 0,108, 0, 7, 0,240, 5, 7, 0,178, 1, 4, 0, 18, 0,222, 0, 85, 0,219, 0,241, 5, +219, 0,242, 5,217, 0,169, 3,218, 0,243, 5, 7, 0,244, 5, 2, 0,245, 5, 2, 0,246, 5, 7, 0,247, 5, 7, 0,248, 5, + 2, 0, 67, 4, 2, 0,249, 5, 7, 0,250, 5, 7, 0,251, 5, 7, 0,252, 5, 2, 0,253, 5, 2, 0,222, 5, 2, 0,254, 5, + 2, 0,255, 5, 2, 0, 0, 6, 2, 0, 1, 6, 7, 0, 2, 6, 7, 0, 3, 6, 7, 0, 4, 6, 2, 0, 5, 6, 2, 0, 6, 6, + 2, 0, 7, 6, 2, 0, 8, 6, 2, 0, 9, 6, 2, 0, 10, 6, 2, 0, 11, 6, 2, 0, 12, 6,214, 0, 13, 6,216, 0, 14, 6, + 7, 0, 15, 6, 7, 0, 16, 6, 7, 0, 17, 6, 2, 0, 18, 6, 2, 0, 19, 6, 0, 0, 20, 6, 0, 0, 21, 6, 2, 0, 22, 6, + 7, 0, 23, 6, 7, 0, 24, 6, 7, 0, 25, 6, 7, 0, 26, 6, 7, 0, 27, 6, 7, 0, 28, 6, 7, 0, 29, 6, 7, 0, 30, 6, + 7, 0, 31, 6, 7, 0, 32, 6, 2, 0, 33, 6, 0, 0, 34, 6, 0, 0, 35, 6, 0, 0, 36, 6, 0, 0, 37, 6, 27, 0, 38, 6, + 0, 0, 39, 6, 0, 0, 40, 6, 0, 0, 41, 6, 0, 0, 42, 6, 0, 0, 43, 6, 0, 0, 44, 6, 0, 0, 45, 6, 0, 0, 46, 6, + 0, 0, 47, 6, 0, 0, 48, 6, 2, 0, 49, 6, 2, 0, 50, 6, 2, 0, 51, 6, 2, 0, 52, 6, 0, 0, 53, 6, 0, 0, 54, 6, + 0, 0, 55, 6, 0, 0, 56, 6, 4, 0, 57, 6, 4, 0, 58, 6, 4, 0, 59, 6, 4, 0, 60, 6, 2, 0, 61, 6, 2, 0, 67, 0, + 4, 0, 62, 6, 7, 0, 63, 6, 7, 0, 64, 6,221, 0, 65, 6,223, 0, 8, 0, 4, 0, 66, 6, 4, 0, 67, 6, 4, 0, 68, 6, + 4, 0, 69, 6, 4, 0, 70, 6, 4, 0, 71, 6, 4, 0, 53, 0, 4, 0,138, 2,224, 0, 4, 0, 7, 0, 72, 6, 0, 0, 73, 6, + 0, 0, 74, 6, 2, 0, 18, 0,225, 0, 4, 0, 7, 0, 75, 6, 4, 0, 18, 0, 4, 0, 76, 6, 4, 0, 56, 0, 41, 0, 46, 0, + 22, 0, 32, 0, 34, 0, 75, 0, 27, 0,208, 5,196, 0, 77, 6, 41, 0, 78, 6, 14, 0, 79, 6,197, 0, 80, 6, 27, 0, 81, 6, + 7, 0, 82, 6, 7, 0, 83, 6, 7, 0, 84, 6, 7, 0, 85, 6, 4, 0,205, 3, 4, 0, 86, 6, 4, 0, 87, 6, 2, 0, 18, 0, + 2, 0, 76, 1, 57, 0, 70, 1,226, 0, 88, 6,222, 0, 89, 6,227, 0, 90, 6,205, 0,185, 0,202, 0, 91, 6, 14, 0,102, 0, + 14, 0, 92, 6, 11, 0, 93, 6, 11, 0, 94, 6, 11, 0, 95, 6, 11, 0, 96, 6, 11, 0, 97, 6,228, 0, 98, 6, 2, 0, 99, 6, + 2, 0,100, 6, 2, 0,251, 0, 2, 0,206, 3, 4, 0,216, 3, 4, 0,101, 6, 14, 0,102, 6,208, 0,194, 5,210, 0,103, 6, +224, 0,104, 6,178, 0,182, 3,225, 0,105, 6,229, 0,106, 6, 10, 0, 7, 4, 10, 0,107, 6,230, 0, 14, 0,230, 0, 0, 0, +230, 0, 1, 0, 42, 0,242, 0, 40, 0, 69, 1,229, 0,106, 6,231, 0,108, 6, 7, 0, 97, 2, 7, 0, 98, 2, 7, 0,108, 0, + 7, 0,109, 6, 2, 0,110, 6, 2, 0, 18, 0, 2, 0,143, 0, 2, 0, 27, 0,232, 0, 39, 0, 7, 0,111, 6, 7, 0,112, 6, + 7, 0,113, 6, 7, 0,114, 6, 7, 0,115, 6, 7, 0,116, 6, 7, 0,117, 6, 7, 0,118, 6, 7, 0,119, 6, 68, 0,120, 6, +178, 0,182, 3,232, 0,121, 6,233, 0,122, 6,234, 0,123, 6,235, 0,124, 6,236, 0,125, 6,237, 0,126, 6, 7, 0,127, 6, + 7, 0,128, 6, 7, 0, 94, 1, 7, 0,129, 6, 7, 0,130, 6, 7, 0,131, 6, 7, 0,132, 6, 7, 0,175, 0, 7, 0,133, 6, + 0, 0,134, 6, 0, 0,135, 6, 0, 0,110, 6, 0, 0,136, 6, 2, 0,137, 6, 2, 0,138, 6, 7, 0,139, 6, 2, 0,140, 6, + 2, 0,141, 6, 7, 0,142, 6, 7, 0,143, 6, 7, 0,144, 6, 7, 0,145, 6,238, 0, 51, 0,239, 0, 0, 0,239, 0, 1, 0, + 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, 7, 0,128, 6, 7, 0, 94, 1, 7, 0,150, 6, 2, 0,151, 6, + 0, 0,211, 2, 4, 0,152, 6, 2, 0,135, 6, 2, 0,110, 6, 27, 0,208, 5, 27, 0,153, 6, 14, 0,154, 6,230, 0,155, 6, +238, 0,121, 6, 0, 0,156, 6, 4, 0,205, 3, 4, 0, 86, 6, 2, 0,157, 6, 2, 0,158, 6, 2, 0,159, 6, 2, 0,160, 6, + 2, 0, 18, 0, 2, 0, 32, 2, 7, 0,114, 0, 7, 0,161, 6, 7, 0,162, 6, 7, 0,163, 6, 7, 0,175, 0, 7, 0, 82, 6, + 2, 0,164, 6, 2, 0,165, 6, 2, 0,166, 6, 0, 0,167, 6, 0, 0,168, 6, 0, 0,169, 6, 0, 0,170, 6, 0, 0,171, 6, + 14, 0,172, 6, 14, 0,173, 6, 14, 0,174, 6, 2, 0,175, 6, 2, 0,152, 2, 2, 0,176, 6, 0, 0,177, 6, 11, 0,178, 6, +178, 0,182, 3,240, 0, 24, 0, 19, 0, 37, 0, 19, 0, 63, 0, 18, 0,179, 6, 18, 0,180, 6, 18, 0,181, 6, 7, 0,182, 6, + 7, 0,183, 6, 7, 0,184, 6, 7, 0,185, 6, 2, 0,186, 6, 2, 0,187, 6, 2, 0,188, 6, 2, 0,189, 6, 2, 0,190, 6, + 2, 0, 18, 0, 2, 0,191, 6, 2, 0,192, 6, 2, 0,193, 6, 2, 0,194, 6, 2, 0,195, 6, 2, 0,160, 6, 7, 0,196, 6, + 4, 0,197, 6, 4, 0,198, 6,239, 0, 6, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, + 2, 0,149, 6,241, 0, 8, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, + 0, 0,199, 6, 0, 0,124, 0,242, 0, 14, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, + 2, 0,149, 6,240, 0,200, 6,243, 0,201, 6, 14, 0,202, 6, 2, 0, 87, 1, 2, 0,203, 6, 4, 0, 18, 0, 7, 0,204, 6, + 4, 0,160, 6,244, 0, 21, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, +240, 0,200, 6, 2, 0,205, 6, 2, 0,206, 6, 2, 0,207, 6, 2, 0,208, 6, 2, 0,191, 6, 2, 0,209, 6, 2, 0,210, 6, + 0, 0, 18, 0, 0, 0, 27, 0, 11, 0, 73, 2, 4, 0,211, 6, 4, 0,212, 6, 22, 0,213, 6, 11, 0,214, 6,245, 0, 18, 0, +239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6,240, 0,200, 6, 7, 0, 97, 2, + 7, 0, 98, 2, 2, 0,205, 6, 2, 0,215, 6, 2, 0,216, 6, 2, 0,217, 6, 4, 0, 18, 0, 7, 0,218, 6, 4, 0,110, 6, + 4, 0, 27, 0,178, 0,182, 3,246, 0, 16, 0, 0, 0,219, 6, 0, 0,220, 6, 0, 0,221, 6, 0, 0,222, 6, 0, 0,223, 6, + 0, 0,224, 6, 4, 0,225, 6, 4, 0,226, 6, 4, 0,227, 6, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0,228, 6, 2, 0,229, 6, + 2, 0,190, 1, 2, 0,230, 6, 0, 0,231, 6,247, 0, 16, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, + 4, 0,232, 6,246, 0,233, 6,248, 0,234, 6, 14, 0,235, 6, 14, 0,236, 6,249, 0,237, 6,237, 0,238, 6,250, 0,239, 6, + 2, 0,240, 6, 2, 0,241, 6, 2, 0,242, 6, 2, 0, 30, 0,251, 0, 15, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, + 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6,240, 0,200, 6, 14, 0,243, 6,252, 0,244, 6, 0, 0,245, 6,253, 0,246, 6, + 2, 0, 18, 0, 2, 0,247, 6, 2, 0,248, 6, 2, 0,249, 6,254, 0, 25, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, + 4, 0,147, 6, 4, 0, 18, 0, 42, 0,244, 2, 40, 0, 69, 1, 54, 0,250, 6,255, 0,251, 6, 0, 1,252, 6,178, 0,182, 3, + 7, 0,253, 6, 7, 0, 97, 2, 7, 0, 98, 2, 7, 0,218, 6, 7, 0,254, 6, 7, 0,255, 6, 2, 0, 0, 7, 2, 0, 27, 0, + 2, 0, 1, 7, 2, 0, 2, 7, 0, 0, 3, 7, 0, 0, 4, 7, 0, 0, 5, 7, 0, 0,160, 6, 1, 1, 11, 0,239, 0, 0, 0, +239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, 2, 0,203, 6, 2, 0, 18, 0, 4, 0, 27, 0, +243, 0,201, 6,240, 0,200, 6, 2, 1, 31, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, + 2, 0,149, 6, 37, 0, 6, 7, 4, 0, 7, 7, 4, 0, 8, 7, 2, 0, 92, 0, 2, 0, 9, 7, 2, 0, 10, 7, 0, 0, 11, 7, + 0, 0, 12, 7, 4, 0, 13, 7, 4, 0, 14, 7, 4, 0, 15, 7, 2, 0, 16, 7, 2, 0, 17, 7, 2, 0, 18, 7, 2, 0, 19, 7, + 7, 0, 20, 7, 18, 0, 21, 7, 18, 0, 22, 7, 4, 0, 23, 7, 4, 0, 24, 7, 0, 0, 25, 7, 0, 0, 26, 7, 2, 0, 27, 7, + 0, 0,211, 2, 11, 0, 28, 7, 3, 1, 10, 0, 22, 0, 32, 0, 11, 0, 29, 7, 11, 0, 30, 7, 11, 0, 31, 7, 11, 0, 32, 7, + 11, 0, 33, 7, 4, 0, 92, 0, 4, 0, 34, 7, 0, 0, 35, 7, 0, 0, 36, 7, 4, 1, 10, 0,239, 0, 0, 0,239, 0, 1, 0, + 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 3, 1, 37, 7, 2, 0, 92, 0, 2, 0, 9, 7, 4, 0, 67, 0, 11, 0, 38, 7, + 5, 1, 3, 0, 5, 1, 0, 0, 5, 1, 1, 0, 7, 0, 39, 7, 6, 1, 9, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, + 4, 0,147, 6, 7, 0,148, 6,240, 0,200, 6, 14, 0, 40, 7, 4, 0, 41, 7, 4, 0, 18, 0, 7, 1, 27, 0,239, 0, 0, 0, +239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6,240, 0,200, 6, 22, 0, 42, 7, 22, 0, 81, 0, + 2, 0, 18, 0, 2, 0, 67, 0, 7, 0, 43, 7, 7, 0, 97, 2, 7, 0, 98, 2, 7, 0,218, 6, 7, 0, 44, 7, 7, 0, 45, 7, + 7, 0, 46, 7, 57, 0, 70, 1, 57, 0, 47, 7, 4, 0, 48, 7, 2, 0, 49, 7, 2, 0, 50, 7, 2, 0,251, 0, 2, 0, 86, 1, + 14, 0, 51, 7,178, 0,182, 3, 8, 1, 10, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, + 2, 0,149, 6, 2, 0, 18, 0, 2, 0,214, 3, 4, 0, 27, 0,178, 0,182, 3, 9, 1, 7, 0, 9, 1, 0, 0, 9, 1, 1, 0, + 4, 0, 52, 7, 4, 0, 22, 0, 0, 0, 86, 0, 4, 0, 53, 7, 4, 0, 16, 0, 10, 1, 14, 0,239, 0, 0, 0,239, 0, 1, 0, + 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, 4, 0, 10, 7, 4, 0, 27, 0, 14, 0, 54, 7, 14, 0, 55, 7, + 0, 0, 56, 7, 0, 0, 57, 7, 4, 0, 58, 7, 4, 0, 59, 7, 11, 1, 6, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, + 4, 0,147, 6, 4, 0, 27, 0, 0, 0, 60, 7, 12, 1, 25, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, + 7, 0, 97, 2, 7, 0, 98, 2, 7, 0, 61, 7, 7, 0, 62, 7, 7, 0,218, 6,231, 0, 63, 7,229, 0,106, 6, 13, 1,251, 6, + 4, 0, 18, 0, 2, 0, 87, 1, 2, 0,110, 6, 4, 0, 64, 7, 7, 0, 65, 7, 7, 0,148, 3, 7, 0, 94, 3, 4, 0, 27, 0, + 7, 0, 66, 7, 7, 0, 67, 7, 4, 0, 68, 7, 4, 0, 30, 0, 11, 0, 69, 7, 14, 1, 7, 0, 14, 1, 0, 0, 14, 1, 1, 0, + 0, 0, 70, 7, 2, 0, 71, 7, 2, 0, 72, 7, 2, 0, 73, 7, 2, 0, 27, 0, 15, 1, 12, 0, 2, 0, 72, 7, 2, 0, 74, 7, + 2, 0, 75, 7, 0, 0,211, 2, 2, 0, 76, 7, 2, 0, 77, 7, 2, 0, 78, 7, 2, 0, 79, 7, 2, 0, 80, 7, 2, 0,191, 6, + 7, 0, 81, 7, 7, 0, 82, 7, 16, 1, 18, 0, 16, 1, 0, 0, 16, 1, 1, 0, 0, 0, 19, 0, 15, 1, 83, 7, 15, 1, 84, 7, + 15, 1, 85, 7, 15, 1, 86, 7, 7, 0, 87, 7, 2, 0, 88, 7, 2, 0, 89, 7, 2, 0, 90, 7, 2, 0, 91, 7, 2, 0, 92, 7, + 2, 0, 93, 7, 2, 0, 94, 7, 2, 0, 95, 7, 2, 0, 96, 7, 2, 0, 27, 0, 17, 1, 10, 0, 0, 0, 97, 7, 0, 0, 98, 7, + 0, 0, 99, 7, 0, 0,100, 7, 0, 0,101, 7, 0, 0,102, 7, 2, 0,103, 7, 2, 0,104, 7, 2, 0,105, 7, 2, 0,106, 7, + 18, 1, 8, 0, 0, 0,107, 7, 0, 0,108, 7, 0, 0,109, 7, 0, 0,110, 7, 0, 0,111, 7, 0, 0,112, 7, 7, 0,109, 6, + 7, 0, 27, 0, 19, 1, 3, 0, 0, 0,113, 7, 2, 0,114, 7, 2, 0, 27, 0, 20, 1, 22, 0, 17, 1,115, 7, 17, 1,116, 7, + 17, 1,117, 7, 17, 1,118, 7, 17, 1,119, 7, 17, 1,120, 7, 17, 1,121, 7, 17, 1,122, 7, 17, 1,123, 7, 17, 1,124, 7, + 17, 1,125, 7, 17, 1,126, 7, 17, 1,127, 7, 17, 1,128, 7, 17, 1,129, 7, 17, 1,130, 7, 17, 1,131, 7, 18, 1,132, 7, + 19, 1,133, 7, 0, 0,134, 7, 7, 0,135, 7, 7, 0, 27, 0, 21, 1,122, 0, 0, 0,136, 7, 0, 0,137, 7, 0, 0,101, 7, + 0, 0,138, 7, 0, 0,113, 7, 0, 0,139, 7, 0, 0,140, 7, 0, 0,141, 7, 0, 0,142, 7, 0, 0,143, 7, 0, 0,144, 7, + 0, 0,145, 7, 0, 0,146, 7, 0, 0,147, 7, 0, 0,148, 7, 0, 0,149, 7, 0, 0,150, 7, 0, 0,151, 7, 0, 0,152, 7, + 0, 0,153, 7, 0, 0,154, 7, 0, 0,155, 7, 0, 0,156, 7, 0, 0,157, 7, 0, 0,158, 7, 0, 0,159, 7, 0, 0,160, 7, + 0, 0,161, 7, 0, 0,162, 7, 0, 0,163, 7, 0, 0,164, 7, 0, 0,165, 7, 0, 0,166, 7, 0, 0,167, 7, 0, 0,168, 7, + 0, 0,169, 7, 0, 0,170, 7, 0, 0,171, 7, 0, 0,172, 7, 0, 0,173, 7, 0, 0,174, 7, 0, 0,175, 7, 0, 0,176, 7, + 0, 0,177, 7, 0, 0,178, 7, 0, 0,179, 7, 0, 0,180, 7, 0, 0,181, 7, 0, 0,182, 7, 0, 0,183, 7, 0, 0,184, 7, + 0, 0,185, 7, 0, 0,186, 7, 0, 0,187, 7, 0, 0,188, 7, 0, 0,189, 7, 0, 0,190, 7, 0, 0,191, 7, 0, 0,192, 7, + 0, 0,193, 7, 0, 0,194, 7, 0, 0,195, 7, 0, 0,196, 7, 0, 0,197, 7, 0, 0,198, 7, 0, 0,199, 7, 0, 0,200, 7, + 0, 0,201, 7, 0, 0,202, 7, 0, 0,203, 7, 0, 0,204, 7, 0, 0,205, 7, 0, 0,206, 7, 0, 0,207, 7, 0, 0,208, 7, + 0, 0,209, 7, 0, 0,210, 7, 0, 0,211, 7, 0, 0,212, 7, 0, 0,213, 7, 0, 0,214, 7, 0, 0,215, 7, 0, 0,216, 7, + 0, 0,217, 7, 0, 0,218, 7, 0, 0,219, 7, 0, 0,220, 7, 0, 0,221, 7, 0, 0,222, 7, 0, 0,223, 7, 0, 0,224, 7, + 0, 0,225, 7, 0, 0,226, 7, 0, 0,227, 7, 0, 0,228, 7, 0, 0,229, 7, 0, 0,230, 7, 0, 0,231, 7, 0, 0,232, 7, + 0, 0,233, 7, 0, 0,234, 7, 0, 0,235, 7, 0, 0,236, 7, 0, 0,237, 7, 0, 0,238, 7, 0, 0,239, 7, 0, 0,240, 7, + 0, 0,241, 7, 0, 0,242, 7, 0, 0,243, 7, 0, 0,244, 7, 0, 0,245, 7, 0, 0,246, 7, 0, 0,247, 7, 0, 0,248, 7, + 0, 0,249, 7, 0, 0,250, 7, 0, 0,251, 7, 0, 0,252, 7, 0, 0,253, 7, 0, 0,254, 7, 0, 0,255, 7, 22, 1, 5, 0, + 0, 0, 0, 8, 0, 0,159, 7, 0, 0,165, 7, 2, 0, 18, 0, 2, 0, 27, 0, 23, 1, 24, 0, 23, 1, 0, 0, 23, 1, 1, 0, + 0, 0,172, 5, 20, 1, 1, 8, 21, 1, 2, 8, 21, 1, 3, 8, 21, 1, 4, 8, 21, 1, 5, 8, 21, 1, 6, 8, 21, 1, 7, 8, + 21, 1, 8, 8, 21, 1, 9, 8, 21, 1, 10, 8, 21, 1, 11, 8, 21, 1, 12, 8, 21, 1, 13, 8, 21, 1, 14, 8, 21, 1, 15, 8, + 21, 1, 16, 8, 21, 1, 17, 8, 21, 1, 18, 8, 22, 1, 19, 8, 4, 0, 20, 8, 4, 0, 27, 0, 24, 1, 3, 0, 24, 1, 0, 0, + 24, 1, 1, 0, 0, 0, 21, 8, 25, 1, 5, 0, 4, 0, 18, 0, 4, 0, 27, 0, 7, 0,151, 2, 7, 0, 22, 8, 7, 0, 47, 2, + 26, 1, 95, 0, 4, 0, 18, 0, 4, 0, 23, 8, 4, 0, 24, 8, 0, 0, 25, 8, 0, 0, 26, 8, 0, 0, 27, 8, 0, 0, 28, 8, + 0, 0, 29, 8, 0, 0, 30, 8, 0, 0, 31, 8, 0, 0, 32, 8, 0, 0, 33, 8, 0, 0, 34, 8, 4, 0, 35, 8, 2, 0, 36, 8, + 2, 0, 37, 8, 2, 0, 38, 8, 2, 0, 39, 8, 4, 0, 40, 8, 4, 0, 41, 8, 4, 0, 42, 8, 4, 0, 43, 8, 2, 0, 44, 8, + 2, 0, 45, 8, 4, 0, 46, 8, 4, 0, 47, 8, 4, 0, 48, 8, 4, 0, 49, 8, 4, 0, 50, 8, 4, 0, 54, 7, 4, 0, 51, 8, + 2, 0, 52, 8, 2, 0, 53, 8, 2, 0, 54, 8, 2, 0, 55, 8, 14, 0, 56, 8, 14, 0, 57, 8, 14, 0, 58, 8, 14, 0, 59, 8, + 14, 0, 60, 8, 14, 0, 61, 8, 0, 0, 62, 8, 2, 0, 63, 8, 2, 0, 64, 8, 2, 0, 65, 8, 2, 0, 66, 8, 2, 0, 67, 8, + 2, 0, 68, 8, 2, 0, 69, 8, 2, 0, 70, 8, 25, 1, 71, 8, 2, 0, 72, 8, 2, 0, 73, 8, 2, 0, 74, 8, 2, 0, 75, 8, + 2, 0, 76, 8, 2, 0, 77, 8, 2, 0, 78, 8, 2, 0, 79, 8, 4, 0, 80, 8, 4, 0, 81, 8, 2, 0, 82, 8, 2, 0, 83, 8, + 2, 0, 84, 8, 2, 0, 85, 8, 2, 0, 86, 8, 2, 0, 87, 8, 2, 0, 88, 8, 2, 0, 89, 8, 2, 0, 90, 8, 2, 0, 91, 8, + 2, 0, 92, 8, 2, 0, 93, 8, 2, 0, 94, 8, 2, 0, 95, 8, 2, 0, 96, 8, 2, 0, 97, 8, 2, 0, 98, 8, 2, 0, 99, 8, + 7, 0,100, 8, 4, 0,101, 8, 7, 0,102, 8, 2, 0, 18, 6, 2, 0, 19, 6, 2, 0,103, 8, 2, 0,104, 8, 50, 0,105, 8, + 7, 0,106, 8, 2, 0,107, 8, 2, 0,247, 1, 0, 0,108, 8, 4, 0,109, 8, 4, 0,110, 8, 7, 0,111, 8, 7, 0, 27, 0, + 27, 1, 24, 0, 22, 0, 32, 0, 14, 0,112, 8, 14, 0,113, 8, 14, 0,114, 8, 14, 0,146, 6, 41, 0,125, 0, 41, 0,115, 8, + 4, 0,116, 8, 4, 0, 67, 0, 2, 0,117, 8, 2, 0,118, 8, 2, 0,119, 8, 2, 0,120, 8, 2, 0,121, 8, 2, 0,122, 8, + 2, 0,123, 8, 2, 0,124, 8, 2, 0,125, 8, 2, 0,126, 8, 2, 0,127, 8, 2, 0, 27, 0,237, 0,128, 8, 11, 0,129, 8, + 2, 0,130, 8, 28, 1, 5, 0, 28, 1, 0, 0, 28, 1, 1, 0, 28, 1,131, 8, 15, 0,132, 8, 4, 0, 18, 0, 29, 1, 7, 0, + 29, 1, 0, 0, 29, 1, 1, 0, 28, 1,133, 8, 28, 1,134, 8, 2, 0,121, 5, 2, 0, 18, 0, 4, 0, 27, 0, 30, 1, 25, 0, + 30, 1, 0, 0, 30, 1, 1, 0, 31, 1,135, 8, 32, 1,239, 6, 0, 0,136, 8, 0, 0,137, 8, 0, 0,138, 8, 2, 0,139, 8, + 2, 0,140, 8, 2, 0,141, 8, 2, 0,142, 8, 2, 0,143, 8, 2, 0, 27, 0, 2, 0, 18, 0, 2, 0,144, 8, 2, 0,145, 8, + 2, 0,146, 8, 4, 0,147, 8, 30, 1,148, 8, 11, 0,149, 8, 4, 0,150, 8, 4, 0,151, 8, 4, 0,152, 8, 4, 0,153, 8, + 0, 0,154, 8, 33, 1, 22, 0, 33, 1, 0, 0, 33, 1, 1, 0, 28, 1,133, 8, 28, 1,134, 8, 28, 1,155, 8, 28, 1,156, 8, + 27, 1,157, 8, 18, 0, 51, 0, 0, 0,147, 6, 0, 0,158, 8, 2, 0,192, 6, 2, 0,193, 6, 2, 0,159, 8, 2, 0, 27, 0, + 2, 0,121, 8, 2, 0, 53, 7, 2, 0, 18, 0, 34, 1,135, 8, 14, 0,160, 8, 14, 0,146, 6, 14, 0,161, 8, 14, 0,162, 8, + 35, 1, 24, 0, 35, 1, 0, 0, 35, 1, 1, 0,240, 0,200, 6, 18, 0,163, 8, 18, 0,164, 8, 2, 0,192, 6, 2, 0,193, 6, + 2, 0,165, 8, 2, 0,166, 8, 2, 0,167, 8, 2, 0, 18, 0, 7, 0, 93, 2, 2, 0,141, 8, 2, 0,142, 8, 2, 0,120, 8, + 2, 0,168, 8, 2, 0,125, 8, 2, 0, 86, 1, 36, 1,135, 8, 14, 0,169, 8, 14, 0,170, 8, 14, 0,161, 8, 0, 0,171, 8, + 11, 0,172, 8, 37, 1, 14, 0, 0, 0,173, 8, 2, 0,174, 8, 2, 0,175, 8, 2, 0,176, 8, 2, 0,177, 8, 2, 0,110, 5, + 2, 0,178, 8, 27, 1,179, 8, 41, 0,180, 8, 4, 0,181, 8, 4, 0,182, 8, 4, 0,183, 8, 4, 0, 27, 0, 0, 0, 70, 7, + 38, 1, 3, 0, 0, 0,184, 8, 4, 0,185, 8, 4, 0,186, 8, 39, 1, 4, 0, 4, 0, 7, 7, 4, 0,187, 8, 4, 0, 13, 7, + 4, 0,188, 8, 40, 1, 2, 0, 4, 0,189, 8, 4, 0,190, 8, 41, 1, 5, 0, 7, 0,191, 8, 7, 0,192, 8, 7, 0,193, 8, + 4, 0, 18, 0, 4, 0, 27, 0, 42, 1, 7, 0, 0, 0,194, 8, 0, 0,221, 6, 44, 0,138, 0, 2, 0,195, 8, 2, 0, 72, 5, + 2, 0,196, 8, 2, 0,197, 8, 43, 1, 12, 0, 43, 1, 0, 0, 43, 1, 1, 0, 4, 0, 28, 0, 4, 0,198, 8, 4, 0,199, 8, + 4, 0,200, 8, 38, 1,201, 8, 0, 0,194, 8, 42, 1,176, 3, 39, 1,202, 8, 40, 1,203, 8, 41, 1,204, 8, 44, 1, 12, 0, + 0, 0, 35, 0, 11, 0,227, 0, 0, 0,228, 0, 4, 0,231, 0, 4, 0,239, 0, 11, 0,232, 0, 7, 0,234, 0, 7, 0,235, 0, + 11, 0,205, 8, 11, 0,206, 8, 11, 0,236, 0, 11, 0,238, 0, 45, 1, 50, 0, 45, 1, 0, 0, 45, 1, 1, 0, 11, 0,207, 8, + 11, 0, 25, 0, 0, 0, 19, 0, 4, 0, 18, 0, 4, 0, 16, 0, 4, 0, 22, 0, 4, 0, 90, 0, 4, 0,208, 8, 4, 0,209, 8, + 4, 0,199, 8, 4, 0,200, 8, 4, 0,210, 8, 4, 0,250, 0, 4, 0,211, 8, 4, 0,212, 8, 7, 0,213, 8, 7, 0,214, 8, + 7, 0,215, 8, 2, 0,216, 8, 2, 0,217, 8, 4, 0,218, 8, 4, 0,219, 8, 43, 1,220, 8, 31, 0, 80, 0, 41, 0,125, 0, + 27, 0,221, 8, 44, 0,138, 0,229, 0,106, 6, 7, 0,222, 8, 7, 0,223, 8, 44, 1, 71, 1, 45, 1,224, 8, 45, 1,225, 8, + 45, 1,226, 8, 14, 0,227, 8, 46, 1,228, 8, 11, 0,229, 8, 7, 0, 84, 4, 7, 0,230, 8, 7, 0,231, 8, 7, 0,232, 8, + 11, 0,233, 8, 4, 0,234, 8, 4, 0,235, 8, 4, 0,236, 8, 7, 0,237, 8, 4, 0,129, 0, 4, 0, 27, 0, 47, 1, 4, 0, + 47, 1, 0, 0, 47, 1, 1, 0, 14, 0,238, 8, 45, 1,239, 8,226, 0, 11, 0, 14, 0,240, 8, 14, 0,227, 8, 14, 0,241, 8, + 45, 1,242, 8, 0, 0,243, 8, 0, 0,244, 8, 4, 0,245, 8, 4, 0,246, 8, 4, 0,247, 8, 4, 0, 27, 0, 19, 0,248, 8, + 48, 1, 4, 0, 7, 0,249, 8, 7, 0, 94, 3, 2, 0,250, 8, 2, 0,251, 8, 49, 1, 6, 0, 7, 0,252, 8, 7, 0,253, 8, + 7, 0,254, 8, 7, 0,255, 8, 4, 0, 0, 9, 4, 0, 1, 9, 50, 1, 8, 0, 7, 0, 2, 9, 7, 0, 3, 9, 7, 0, 4, 9, + 7, 0, 5, 9, 7, 0, 6, 9, 4, 0,250, 2, 4, 0, 7, 9, 4, 0, 8, 9, 51, 1, 2, 0, 7, 0,180, 5, 7, 0, 27, 0, + 52, 1, 5, 0, 7, 0, 9, 9, 7, 0, 10, 9, 4, 0, 92, 0, 4, 0,212, 2, 4, 0, 11, 9, 53, 1, 6, 0, 53, 1, 0, 0, + 53, 1, 1, 0, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 12, 9, 2, 0, 56, 0, 54, 1, 8, 0, 54, 1, 0, 0, 54, 1, 1, 0, + 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 12, 9, 2, 0, 56, 0, 7, 0, 22, 0, 7, 0,129, 0, 55, 1, 45, 0, 55, 1, 0, 0, + 55, 1, 1, 0, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 12, 9, 2, 0,246, 0, 2, 0,126, 4, 2, 0, 13, 9, 7, 0, 14, 9, + 7, 0, 91, 0, 7, 0, 7, 3, 4, 0, 15, 9, 4, 0, 82, 0, 4, 0,214, 2, 7, 0, 16, 9, 7, 0, 17, 9, 7, 0, 18, 9, + 7, 0, 19, 9, 7, 0, 20, 9, 7, 0, 21, 9, 7, 0, 4, 3, 7, 0, 68, 1, 7, 0, 22, 9, 7, 0, 23, 9, 7, 0, 27, 0, + 7, 0, 24, 9, 7, 0, 25, 9, 7, 0, 26, 9, 2, 0, 27, 9, 2, 0, 28, 9, 2, 0, 29, 9, 2, 0, 30, 9, 2, 0, 31, 9, + 2, 0, 32, 9, 2, 0, 33, 9, 2, 0, 34, 9, 2, 0, 32, 2, 2, 0, 35, 9, 2, 0, 29, 2, 2, 0, 36, 9, 0, 0, 37, 9, + 0, 0, 38, 9, 7, 0,244, 0, 56, 1, 39, 9, 64, 0,250, 1, 57, 1, 16, 0, 57, 1, 0, 0, 57, 1, 1, 0, 2, 0, 16, 0, + 2, 0, 18, 0, 2, 0, 12, 9, 2, 0,246, 0, 7, 0,255, 2, 7, 0, 0, 3, 7, 0, 1, 3, 7, 0, 82, 2, 7, 0, 2, 3, + 7, 0, 3, 3, 7, 0, 40, 9, 7, 0, 4, 3, 7, 0, 6, 3, 7, 0, 7, 3,253, 0, 5, 0, 2, 0, 16, 0, 2, 0, 41, 9, + 2, 0, 18, 0, 2, 0, 42, 9, 22, 0, 42, 7,252, 0, 3, 0, 4, 0, 69, 0, 4, 0, 43, 9,253, 0, 2, 0, 58, 1, 7, 0, + 58, 1, 0, 0, 58, 1, 1, 0, 0, 0, 19, 0, 2, 0, 16, 0, 2, 0, 18, 0, 4, 0, 21, 0, 11, 0, 44, 9, 59, 1, 5, 0, + 0, 0, 19, 0, 7, 0, 94, 1, 7, 0, 45, 9, 4, 0, 46, 9, 4, 0, 27, 0, 60, 1, 4, 0, 2, 0, 16, 0, 2, 0, 18, 0, + 2, 0, 67, 0, 2, 0, 30, 0, 61, 1, 4, 0, 0, 0, 19, 0, 63, 0, 47, 9, 7, 0, 94, 1, 7, 0, 27, 0, 62, 1, 6, 0, + 2, 0, 48, 9, 2, 0, 49, 9, 2, 0, 16, 0, 2, 0, 50, 9, 0, 0, 51, 9, 0, 0, 52, 9, 63, 1, 5, 0, 4, 0, 16, 0, + 4, 0, 27, 0, 0, 0, 19, 0, 0, 0, 53, 9, 0, 0, 54, 9, 64, 1, 3, 0, 4, 0, 16, 0, 4, 0, 27, 0, 0, 0, 19, 0, + 65, 1, 4, 0, 2, 0, 55, 9, 2, 0, 56, 9, 2, 0, 18, 0, 2, 0, 27, 0, 66, 1, 6, 0, 0, 0, 19, 0, 0, 0, 57, 9, + 2, 0, 58, 9, 2, 0, 4, 3, 2, 0, 87, 1, 2, 0, 30, 0, 67, 1, 5, 0, 0, 0, 19, 0, 7, 0, 94, 3, 7, 0,217, 4, + 2, 0, 18, 0, 2, 0,226, 2, 68, 1, 3, 0, 0, 0, 19, 0, 4, 0,214, 2, 4, 0, 55, 9, 69, 1, 7, 0, 0, 0, 19, 0, + 7, 0,217, 4, 0, 0, 59, 9, 0, 0, 60, 9, 2, 0, 87, 1, 2, 0, 67, 0, 4, 0, 61, 9, 70, 1, 4, 0, 0, 0, 62, 9, + 0, 0, 63, 9, 4, 0, 16, 0, 7, 0,230, 2, 71, 1, 3, 0, 27, 0, 64, 9, 0, 0, 65, 9, 0, 0, 66, 9, 72, 1, 18, 0, + 72, 1, 0, 0, 72, 1, 1, 0, 2, 0, 16, 0, 2, 0, 67, 9, 2, 0, 18, 0, 2, 0, 68, 9, 2, 0, 69, 9, 2, 0, 70, 9, + 2, 0, 67, 0, 2, 0, 30, 0, 0, 0, 19, 0, 11, 0, 2, 0, 73, 1, 71, 9, 27, 0, 44, 0, 2, 0,216, 5, 2, 0,176, 2, + 2, 0, 72, 9, 2, 0, 27, 0, 74, 1, 11, 0, 0, 0, 19, 0, 0, 0, 16, 0, 0, 0, 73, 9, 2, 0, 18, 0, 2, 0,226, 2, + 2, 0, 74, 9, 4, 0, 75, 9, 4, 0, 76, 9, 4, 0, 77, 9, 4, 0, 78, 9, 4, 0, 79, 9, 75, 1, 1, 0, 0, 0, 80, 9, 76, 1, 4, 0, 37, 0, 6, 7, 0, 0, 21, 8, 4, 0, 87, 1, 4, 0, 18, 0, 73, 1, 18, 0, 73, 1, 0, 0, 73, 1, 1, 0, - 73, 1, 80, 9, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 81, 9, 2, 0, 69, 9, 2, 0, 66, 9, 2, 0, 82, 9, 2, 0, 30, 0, - 2, 0, 74, 0, 0, 0, 19, 0, 11, 0, 2, 0, 77, 1, 70, 9, 72, 1, 83, 9, 2, 0, 14, 0, 2, 0, 84, 9, 4, 0, 85, 9, - 78, 1, 3, 0, 4, 0,240, 2, 4, 0, 27, 0, 27, 0, 44, 0, 79, 1, 15, 0,176, 0, 86, 9, 2, 0, 16, 0, 2, 0, 18, 0, - 7, 0, 13, 9, 7, 0, 90, 0, 0, 0, 19, 0, 0, 0, 87, 9, 2, 0, 88, 9, 2, 0, 89, 9, 2, 0,134, 0, 2, 0, 90, 9, - 2, 0, 91, 9, 2, 0, 27, 0, 7, 0, 92, 9, 7, 0, 93, 9, 80, 1, 8, 0, 7, 0, 94, 9, 7, 0, 95, 9, 7, 0, 96, 9, - 7, 0, 97, 9, 7, 0, 98, 9, 7, 0, 99, 9, 7, 0,100, 9, 7, 0,101, 9, 81, 1, 13, 0, 2, 0, 18, 0, 2, 0,102, 9, - 4, 0, 91, 0, 4, 0, 30, 0, 2, 0,177, 6, 7, 0, 84, 4, 7, 0,229, 8, 46, 1,227, 8, 80, 1,103, 9, 2, 0, 16, 0, - 2, 0,115, 5, 2, 0,216, 3, 2, 0,104, 9, 82, 1, 11, 0, 4, 0,240, 2, 2, 0, 16, 0, 2, 0, 18, 0, 27, 0, 44, 0, - 79, 0,105, 9, 0, 0, 19, 0, 7, 0,106, 9, 7, 0,107, 9, 7, 0,222, 3, 2, 0,108, 9, 2, 0,109, 9, 83, 1, 5, 0, - 2, 0, 16, 0, 2, 0, 91, 0, 4, 0, 27, 0, 41, 0,125, 0, 27, 0,208, 5, 84, 1, 5, 0, 4, 0, 27, 0, 4, 0, 16, 0, - 0, 0, 19, 0, 0, 0, 52, 9, 27, 0, 44, 0, 85, 1, 13, 0, 2, 0, 18, 0, 2, 0, 16, 0, 2, 0, 66, 9, 2, 0,223, 3, - 7, 0,110, 9, 7, 0,111, 9, 7, 0, 86, 1, 7, 0,112, 9, 7, 0,192, 3, 7, 0,196, 3, 7, 0,113, 9, 7, 0,114, 9, - 27, 0,115, 9, 86, 1, 10, 0, 2, 0, 18, 0, 2, 0, 16, 0, 7, 0, 13, 9, 7, 0, 90, 0, 0, 0, 19, 0, 0, 0, 87, 9, - 2, 0, 91, 0, 2, 0, 30, 0, 2, 0, 74, 0, 2, 0,115, 5, 87, 1, 8, 0, 27, 0, 44, 0, 7, 0, 1, 3, 7, 0,116, 9, - 7, 0,117, 9, 7, 0,223, 3, 2, 0, 91, 0, 2, 0,226, 2, 7, 0, 30, 0, 88, 1, 12, 0, 2, 0, 16, 0, 2, 0, 87, 1, - 2, 0, 18, 0, 2, 0, 4, 3, 2, 0,240, 2, 2, 0,118, 9, 4, 0, 27, 0, 7, 0,119, 9, 7, 0,120, 9, 7, 0,121, 9, - 7, 0,122, 9, 0, 0,123, 9, 89, 1, 9, 0, 2, 0, 18, 0, 2, 0, 16, 0, 4, 0, 13, 9, 4, 0, 90, 0, 0, 0, 19, 0, - 2, 0, 86, 1, 2, 0, 63, 0, 2, 0,124, 9, 2, 0,125, 9, 90, 1, 7, 0, 4, 0,214, 2, 4, 0,126, 9, 4, 0,127, 9, - 4, 0,128, 9, 7, 0,129, 9, 7, 0,130, 9, 0, 0, 58, 9, 91, 1, 7, 0, 0, 0,131, 9, 27, 0,132, 9, 0, 0, 64, 9, - 2, 0,133, 9, 2, 0, 91, 0, 4, 0, 30, 0, 0, 0, 65, 9, 92, 1, 6, 0, 2, 0, 18, 0, 2, 0, 16, 0, 4, 0, 13, 9, - 4, 0, 90, 0, 0, 0,134, 9, 0, 0,135, 9, 93, 1, 1, 0, 4, 0, 18, 0, 94, 1, 6, 0, 0, 0, 94, 0, 2, 0, 16, 0, - 2, 0, 18, 0, 4, 0,136, 9, 7, 0,137, 9, 37, 0, 6, 7, 95, 1, 4, 0, 0, 0,181, 2, 2, 0, 18, 0, 4, 0, 16, 0, - 27, 0, 44, 0, 96, 1, 2, 0, 4, 0, 16, 0, 4, 0,181, 6, 97, 1, 8, 0, 0, 0, 61, 9, 0, 0, 62, 9, 4, 0, 16, 0, - 7, 0, 39, 2, 7, 0,138, 9, 7, 0, 27, 0, 27, 0, 70, 3, 27, 0,139, 9, 98, 1, 11, 0, 0, 0, 54, 6, 0, 0, 18, 0, - 2, 0,140, 9, 4, 0, 16, 0, 7, 0, 94, 1, 7, 0,141, 9, 7, 0,142, 9, 7, 0,143, 9, 4, 0,144, 9, 27, 0, 70, 3, - 27, 0,145, 9, 77, 1, 10, 0, 77, 1, 0, 0, 77, 1, 1, 0, 77, 1, 80, 9, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 66, 9, - 2, 0,146, 9, 0, 0, 19, 0, 11, 0, 2, 0, 27, 0, 44, 0, 46, 1, 17, 0, 22, 0, 32, 0, 0, 0, 35, 0, 38, 0,153, 0, - 11, 0,227, 0, 38, 0,147, 9, 31, 0, 80, 0, 7, 0, 84, 4, 7, 0,148, 9, 7, 0,229, 8, 7, 0, 94, 9, 7, 0, 95, 9, - 7, 0,149, 9, 4, 0, 92, 0, 4, 0, 27, 0, 11, 0,150, 9, 11, 0,151, 9, 11, 0,152, 9, 99, 1, 6, 0, 99, 1, 0, 0, - 99, 1, 1, 0, 27, 0, 44, 0, 11, 0,153, 9, 2, 0,251, 0, 0, 0,211, 2, 64, 0, 4, 0, 22, 0, 32, 0, 14, 0,154, 9, - 4, 0,134, 0, 7, 0,155, 9,100, 1, 28, 0,100, 1, 0, 0,100, 1, 1, 0, 21, 0,156, 9,100, 1, 38, 0, 14, 0,157, 9, - 0, 0, 19, 0, 7, 0,158, 9, 7, 0,159, 9, 7, 0,160, 9, 7, 0,161, 9, 4, 0, 18, 0, 7, 0,162, 9, 7, 0,163, 9, - 7, 0,164, 9, 7, 0,165, 9, 7, 0, 94, 1, 7, 0, 39, 2, 7, 0,166, 9, 7, 0,212, 2, 7, 0,167, 9, 7, 0,168, 9, - 7, 0,169, 9, 7, 0,170, 9, 7, 0,171, 9, 7, 0,176, 0, 4, 0,134, 0, 2, 0,254, 5, 2, 0,172, 9,101, 1, 27, 0, - 22, 0, 32, 0, 34, 0, 75, 0, 14, 0,173, 9, 14, 0,174, 9, 14, 0,175, 9,100, 1,176, 9, 11, 0,177, 9, 11, 0,178, 9, - 4, 0, 18, 0, 4, 0,157, 6, 4, 0,179, 9, 4, 0, 27, 0, 2, 0, 8, 3, 2, 0,211, 6, 4, 0,180, 9, 4, 0,134, 0, - 4, 0,181, 9, 2, 0,182, 9, 2, 0,183, 9, 2, 0,184, 9, 2, 0,185, 9, 4, 0,186, 9, 4, 0,187, 9, 4, 0,188, 9, - 4, 0,189, 9, 4, 0,190, 9, 4, 0,191, 9,102, 1, 2, 0, 7, 0,165, 2, 4, 0, 18, 0,180, 0, 5, 0,102, 1,192, 9, - 4, 0,212, 2, 4, 0,193, 9, 4, 0,194, 9, 4, 0, 18, 0,179, 0, 16, 0, 4, 0,195, 9, 4, 0,196, 9, 4, 0,197, 9, - 4, 0,198, 9, 2, 0,199, 9, 2, 0,200, 9, 2, 0,201, 9, 2, 0,251, 0, 2, 0,202, 9, 2, 0,203, 9, 2, 0,204, 9, - 2, 0,205, 9, 4, 0,206, 9, 4, 0,207, 9, 4, 0,208, 9, 4, 0,209, 9,103, 1, 40, 0,103, 1, 0, 0,103, 1, 1, 0, - 21, 0,156, 9, 14, 0,251, 3, 0, 0, 19, 0, 2, 0, 18, 0, 2, 0,210, 9, 2, 0,209, 3, 2, 0,211, 9, 0, 0,212, 9, - 0, 0,213, 9, 0, 0,214, 9,100, 1,215, 9,103, 1, 38, 0,103, 1,216, 9, 14, 0,217, 9, 14, 0,218, 9,180, 0,184, 3, - 27, 0,219, 9,103, 1,220, 9, 7, 0, 77, 1, 7, 0,176, 0, 7, 0,221, 9, 7, 0, 18, 2, 7, 0,198, 3, 7, 0,200, 3, - 2, 0,232, 3, 2, 0, 27, 0, 7, 0,222, 9, 7, 0,223, 9, 7, 0,203, 3, 7, 0,224, 9, 7, 0,225, 9, 7, 0,226, 9, - 7, 0,227, 9, 7, 0,228, 9, 7, 0,229, 9, 7, 0,230, 9, 7, 0,231, 9, 11, 0,232, 9,177, 0, 16, 0, 14, 0,233, 9, - 74, 0,234, 9, 2, 0, 18, 0, 2, 0, 27, 0, 4, 0,235, 9, 4, 0, 91, 0, 7, 0,108, 2, 7, 0,236, 9, 7, 0,237, 9, - 14, 0,238, 9, 4, 0,239, 9, 4, 0,240, 9, 11, 0,241, 9, 11, 0,242, 9,179, 0,183, 3, 0, 0,243, 9,104, 1, 1, 0, - 4, 0,240, 9,105, 1, 12, 0, 4, 0,240, 9, 7, 0, 78, 9, 2, 0,244, 9, 2, 0,245, 9, 7, 0,246, 9, 7, 0,247, 9, - 2, 0,248, 9, 2, 0, 18, 0, 7, 0,249, 9, 7, 0,250, 9, 7, 0,251, 9, 7, 0,252, 9,106, 1, 7, 0,106, 1, 0, 0, -106, 1, 1, 0, 14, 0,253, 9, 4, 0, 18, 0, 4, 0,254, 9, 0, 0, 19, 0, 22, 1,255, 9,176, 0, 9, 0, 22, 0, 32, 0, - 14, 0, 0, 10, 14, 0,233, 9, 14, 0, 1, 10, 14, 0,102, 0, 4, 0, 18, 0, 4, 0, 2, 10, 4, 0, 3, 10, 4, 0, 27, 0, -243, 0, 8, 0, 22, 0, 4, 10, 14, 0,233, 9, 64, 0, 5, 10, 0, 0, 6, 10, 4, 0, 7, 10, 4, 0, 18, 0, 4, 0, 8, 10, + 73, 1, 81, 9, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 82, 9, 2, 0, 70, 9, 2, 0, 67, 9, 2, 0, 83, 9, 2, 0, 30, 0, + 2, 0,247, 1, 0, 0, 19, 0, 11, 0, 2, 0, 77, 1, 71, 9, 72, 1, 84, 9, 2, 0, 14, 0, 2, 0, 85, 9, 4, 0, 86, 9, + 78, 1, 3, 0, 4, 0,240, 2, 4, 0, 27, 0, 27, 0, 44, 0, 79, 1, 15, 0,176, 0, 87, 9, 2, 0, 16, 0, 2, 0, 18, 0, + 7, 0, 14, 9, 7, 0, 91, 0, 0, 0, 19, 0, 0, 0, 88, 9, 2, 0, 89, 9, 2, 0, 90, 9, 2, 0,134, 0, 2, 0, 91, 9, + 2, 0, 92, 9, 2, 0, 27, 0, 7, 0, 93, 9, 7, 0, 94, 9, 80, 1, 8, 0, 7, 0, 95, 9, 7, 0, 96, 9, 7, 0, 97, 9, + 7, 0, 98, 9, 7, 0, 99, 9, 7, 0,100, 9, 7, 0,101, 9, 7, 0,102, 9, 81, 1, 13, 0, 2, 0, 18, 0, 2, 0,103, 9, + 4, 0, 67, 0, 4, 0, 30, 0, 2, 0,177, 6, 7, 0, 84, 4, 7, 0,230, 8, 46, 1,228, 8, 80, 1,104, 9, 2, 0, 16, 0, + 2, 0,115, 5, 2, 0,216, 3, 2, 0,105, 9, 82, 1, 11, 0, 4, 0,240, 2, 2, 0, 16, 0, 2, 0, 18, 0, 27, 0, 44, 0, + 79, 0,106, 9, 0, 0, 19, 0, 7, 0,107, 9, 7, 0,108, 9, 7, 0,222, 3, 2, 0,109, 9, 2, 0,110, 9, 83, 1, 5, 0, + 2, 0, 16, 0, 2, 0, 67, 0, 4, 0, 27, 0, 41, 0,125, 0, 27, 0,208, 5, 84, 1, 5, 0, 4, 0, 27, 0, 4, 0, 16, 0, + 0, 0, 19, 0, 0, 0, 53, 9, 27, 0, 44, 0, 85, 1, 13, 0, 2, 0, 18, 0, 2, 0, 16, 0, 2, 0, 67, 9, 2, 0,223, 3, + 7, 0,111, 9, 7, 0,112, 9, 7, 0, 86, 1, 7, 0,113, 9, 7, 0,192, 3, 7, 0,196, 3, 7, 0,114, 9, 7, 0,115, 9, + 27, 0,116, 9, 86, 1, 10, 0, 2, 0, 18, 0, 2, 0, 16, 0, 7, 0, 14, 9, 7, 0, 91, 0, 0, 0, 19, 0, 0, 0, 88, 9, + 2, 0, 67, 0, 2, 0, 30, 0, 2, 0,247, 1, 2, 0,115, 5, 87, 1, 8, 0, 27, 0, 44, 0, 7, 0, 1, 3, 7, 0,117, 9, + 7, 0,118, 9, 7, 0,223, 3, 2, 0, 67, 0, 2, 0,226, 2, 7, 0, 30, 0, 88, 1, 12, 0, 2, 0, 16, 0, 2, 0, 87, 1, + 2, 0, 18, 0, 2, 0, 4, 3, 2, 0,240, 2, 2, 0,119, 9, 4, 0, 27, 0, 7, 0,120, 9, 7, 0,121, 9, 7, 0,122, 9, + 7, 0,123, 9, 0, 0,124, 9, 89, 1, 9, 0, 2, 0, 18, 0, 2, 0, 16, 0, 4, 0, 14, 9, 4, 0, 91, 0, 0, 0, 19, 0, + 2, 0, 86, 1, 2, 0, 63, 0, 2, 0,125, 9, 2, 0,126, 9, 90, 1, 7, 0, 4, 0,214, 2, 4, 0,127, 9, 4, 0,128, 9, + 4, 0,129, 9, 7, 0,130, 9, 7, 0,131, 9, 0, 0, 59, 9, 91, 1, 7, 0, 0, 0,132, 9, 27, 0,133, 9, 0, 0, 65, 9, + 2, 0,134, 9, 2, 0, 67, 0, 4, 0, 30, 0, 0, 0, 66, 9, 92, 1, 6, 0, 2, 0, 18, 0, 2, 0, 16, 0, 4, 0, 14, 9, + 4, 0, 91, 0, 0, 0,135, 9, 0, 0,136, 9, 93, 1, 1, 0, 4, 0, 18, 0, 94, 1, 6, 0, 0, 0, 94, 0, 2, 0, 16, 0, + 2, 0, 18, 0, 4, 0,137, 9, 7, 0,138, 9, 37, 0, 6, 7, 95, 1, 4, 0, 0, 0,181, 2, 2, 0, 18, 0, 4, 0, 16, 0, + 27, 0, 44, 0, 96, 1, 2, 0, 4, 0, 16, 0, 4, 0,181, 6, 97, 1, 8, 0, 0, 0, 62, 9, 0, 0, 63, 9, 4, 0, 16, 0, + 7, 0, 40, 2, 7, 0,139, 9, 7, 0, 27, 0, 27, 0, 70, 3, 27, 0,140, 9, 98, 1, 11, 0, 0, 0, 54, 6, 0, 0, 18, 0, + 2, 0,141, 9, 4, 0, 16, 0, 7, 0, 94, 1, 7, 0,142, 9, 7, 0,143, 9, 7, 0,144, 9, 4, 0,145, 9, 27, 0, 70, 3, + 27, 0,146, 9, 77, 1, 10, 0, 77, 1, 0, 0, 77, 1, 1, 0, 77, 1, 81, 9, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 67, 9, + 2, 0,147, 9, 0, 0, 19, 0, 11, 0, 2, 0, 27, 0, 44, 0, 46, 1, 17, 0, 22, 0, 32, 0, 0, 0, 35, 0, 38, 0,153, 0, + 11, 0,227, 0, 38, 0,148, 9, 31, 0, 80, 0, 7, 0, 84, 4, 7, 0,149, 9, 7, 0,230, 8, 7, 0, 95, 9, 7, 0, 96, 9, + 7, 0,150, 9, 4, 0, 92, 0, 4, 0, 27, 0, 11, 0,151, 9, 11, 0,152, 9, 11, 0,153, 9, 99, 1, 6, 0, 99, 1, 0, 0, + 99, 1, 1, 0, 27, 0, 44, 0, 11, 0,154, 9, 2, 0,251, 0, 0, 0,211, 2, 64, 0, 4, 0, 22, 0, 32, 0, 14, 0,155, 9, + 4, 0,134, 0, 7, 0,156, 9,100, 1, 28, 0,100, 1, 0, 0,100, 1, 1, 0, 21, 0,157, 9,100, 1, 38, 0, 14, 0,158, 9, + 0, 0, 19, 0, 7, 0,159, 9, 7, 0,160, 9, 7, 0,161, 9, 7, 0,162, 9, 4, 0, 18, 0, 7, 0,163, 9, 7, 0,164, 9, + 7, 0,165, 9, 7, 0,166, 9, 7, 0, 94, 1, 7, 0, 40, 2, 7, 0,167, 9, 7, 0,212, 2, 7, 0,168, 9, 7, 0,169, 9, + 7, 0,170, 9, 7, 0,171, 9, 7, 0,172, 9, 7, 0,176, 0, 4, 0,134, 0, 2, 0,254, 5, 2, 0,173, 9,101, 1, 27, 0, + 22, 0, 32, 0, 34, 0, 75, 0, 14, 0,174, 9, 14, 0,175, 9, 14, 0,176, 9,100, 1,177, 9, 11, 0,178, 9, 11, 0,179, 9, + 4, 0, 18, 0, 4, 0,157, 6, 4, 0,180, 9, 4, 0, 27, 0, 2, 0, 8, 3, 2, 0,211, 6, 4, 0,181, 9, 4, 0,134, 0, + 4, 0,182, 9, 2, 0,183, 9, 2, 0,184, 9, 2, 0,185, 9, 2, 0,186, 9, 4, 0,187, 9, 4, 0,188, 9, 4, 0,189, 9, + 4, 0,190, 9, 4, 0,191, 9, 4, 0,192, 9,102, 1, 2, 0, 7, 0,165, 2, 4, 0, 18, 0,180, 0, 5, 0,102, 1,193, 9, + 4, 0,212, 2, 4, 0,194, 9, 4, 0,195, 9, 4, 0, 18, 0,179, 0, 16, 0, 4, 0,196, 9, 4, 0,197, 9, 4, 0,198, 9, + 4, 0,199, 9, 2, 0,200, 9, 2, 0,201, 9, 2, 0,202, 9, 2, 0,251, 0, 2, 0,203, 9, 2, 0,204, 9, 2, 0,205, 9, + 2, 0,206, 9, 4, 0,207, 9, 4, 0,208, 9, 4, 0,209, 9, 4, 0,210, 9,103, 1, 40, 0,103, 1, 0, 0,103, 1, 1, 0, + 21, 0,157, 9, 14, 0,251, 3, 0, 0, 19, 0, 2, 0, 18, 0, 2, 0,211, 9, 2, 0,209, 3, 2, 0,212, 9, 0, 0,213, 9, + 0, 0,214, 9, 0, 0,215, 9,100, 1,216, 9,103, 1, 38, 0,103, 1,217, 9, 14, 0,218, 9, 14, 0,219, 9,180, 0,184, 3, + 27, 0,220, 9,103, 1,221, 9, 7, 0, 77, 1, 7, 0,176, 0, 7, 0,222, 9, 7, 0, 19, 2, 7, 0,198, 3, 7, 0,200, 3, + 2, 0,232, 3, 2, 0, 27, 0, 7, 0,223, 9, 7, 0,224, 9, 7, 0,203, 3, 7, 0,225, 9, 7, 0,226, 9, 7, 0,227, 9, + 7, 0,228, 9, 7, 0,229, 9, 7, 0,230, 9, 7, 0,231, 9, 7, 0,232, 9, 11, 0,233, 9,177, 0, 16, 0, 14, 0,234, 9, + 74, 0,235, 9, 2, 0, 18, 0, 2, 0, 27, 0, 4, 0,236, 9, 4, 0, 67, 0, 7, 0, 84, 0, 7, 0,237, 9, 7, 0,238, 9, + 14, 0,239, 9, 4, 0,240, 9, 4, 0,241, 9, 11, 0,242, 9, 11, 0,243, 9,179, 0,183, 3, 0, 0,244, 9,104, 1, 1, 0, + 4, 0,241, 9,105, 1, 12, 0, 4, 0,241, 9, 7, 0, 79, 9, 2, 0,245, 9, 2, 0,246, 9, 7, 0,247, 9, 7, 0,248, 9, + 2, 0,249, 9, 2, 0, 18, 0, 7, 0,250, 9, 7, 0,251, 9, 7, 0,252, 9, 7, 0,253, 9,106, 1, 7, 0,106, 1, 0, 0, +106, 1, 1, 0, 14, 0,254, 9, 4, 0, 18, 0, 4, 0,255, 9, 0, 0, 19, 0, 22, 1, 0, 10,176, 0, 9, 0, 22, 0, 32, 0, + 14, 0, 1, 10, 14, 0,234, 9, 14, 0, 2, 10, 14, 0,102, 0, 4, 0, 18, 0, 4, 0, 3, 10, 4, 0, 4, 10, 4, 0, 27, 0, +243, 0, 8, 0, 22, 0, 5, 10, 14, 0,234, 9, 64, 0, 6, 10, 0, 0, 7, 10, 4, 0, 8, 10, 4, 0, 18, 0, 4, 0, 9, 10, 4, 0, 27, 0,107, 1, 13, 0,239, 0, 0, 0,239, 0, 1, 0, 14, 0,146, 6, 4, 0,147, 6, 7, 0,148, 6, 2, 0,149, 6, -240, 0,200, 6,176, 0,179, 3,243, 0, 9, 10, 0, 0, 87, 1, 0, 0,203, 6, 2, 0, 18, 0, 7, 0, 10, 10,108, 1, 8, 0, -108, 1, 0, 0,108, 1, 1, 0,106, 1, 11, 10, 31, 0, 80, 0, 14, 0,185, 3, 4, 0, 18, 0, 0, 0, 19, 0, 4, 0,118, 8, -109, 1, 5, 0,109, 1, 0, 0,109, 1, 1, 0, 31, 0, 80, 0, 2, 0, 18, 0, 0, 0, 12, 10,110, 1, 14, 0,110, 1, 0, 0, -110, 1, 1, 0, 11, 0, 2, 0, 2, 0, 16, 0, 2, 0, 18, 0, 0, 0, 13, 10, 0, 0, 14, 10, 0, 0, 19, 0, 2, 0, 27, 0, - 7, 0, 15, 10, 7, 0, 16, 10, 31, 0, 80, 0, 7, 0, 17, 10, 7, 0, 18, 10,111, 1, 9, 0,111, 1, 0, 0,111, 1, 1, 0, - 27, 0, 19, 10, 0, 0, 11, 3, 7, 0, 20, 10, 2, 0, 21, 10, 2, 0, 18, 0, 2, 0, 16, 0, 2, 0, 22, 10,112, 1, 7, 0, - 37, 0, 6, 7, 21, 0,156, 9, 4, 0, 18, 0, 4, 0, 23, 10, 14, 0, 24, 10, 27, 0, 19, 10, 0, 0, 11, 3,113, 1, 15, 0, - 27, 0, 19, 10, 2, 0, 25, 10, 2, 0, 18, 0, 2, 0, 26, 10, 2, 0, 27, 10, 0, 0, 11, 3, 27, 0, 28, 10, 0, 0, 29, 10, - 7, 0, 30, 10, 7, 0, 39, 2, 7, 0, 31, 10, 7, 0, 32, 10, 2, 0, 16, 0, 2, 0, 87, 1, 7, 0, 94, 1,114, 1, 6, 0, - 27, 0, 19, 10, 7, 0,192, 9, 2, 0, 33, 10, 2, 0, 34, 10, 2, 0, 18, 0, 2, 0, 35, 10,115, 1, 6, 0, 27, 0, 19, 10, - 4, 0, 36, 10, 4, 0, 37, 10, 4, 0, 92, 0, 4, 0, 27, 0, 0, 0, 11, 3,116, 1, 4, 0, 27, 0, 19, 10, 4, 0, 18, 0, - 4, 0, 36, 10, 0, 0, 11, 3,117, 1, 4, 0, 27, 0, 19, 10, 4, 0, 18, 0, 4, 0, 36, 10, 0, 0, 11, 3,118, 1, 4, 0, - 27, 0, 19, 10, 4, 0, 18, 0, 4, 0, 36, 10, 0, 0, 11, 3,119, 1, 2, 0, 4, 0, 18, 0, 7, 0, 84, 4,120, 1, 2, 0, - 27, 0, 19, 10, 0, 0, 11, 3,121, 1, 10, 0, 27, 0, 19, 10, 4, 0, 38, 10, 7, 0,128, 0, 4, 0, 18, 0, 2, 0, 4, 7, - 2, 0, 39, 10, 2, 0, 91, 0, 2, 0, 30, 0, 7, 0, 40, 10, 0, 0, 11, 3,122, 1, 10, 0, 27, 0, 19, 10, 2, 0, 16, 0, - 2, 0,134, 4, 4, 0, 89, 0, 4, 0, 90, 0, 7, 0,116, 9, 7, 0,117, 9, 4, 0, 27, 0,176, 0, 86, 9, 0, 0, 11, 3, -123, 1, 4, 0, 27, 0, 19, 10, 4, 0,210, 3, 4, 0, 41, 10, 0, 0, 11, 3,124, 1, 4, 0, 27, 0, 19, 10, 4, 0,210, 3, - 4, 0, 27, 0, 0, 0, 11, 3,125, 1, 6, 0, 27, 0, 19, 10, 7, 0,128, 0, 7, 0, 82, 3, 4, 0, 42, 10, 2, 0,210, 3, - 2, 0,211, 3,126, 1, 6, 0, 27, 0, 19, 10, 4, 0, 43, 10, 4, 0, 44, 10, 7, 0, 45, 10, 7, 0, 46, 10, 0, 0, 11, 3, -127, 1, 16, 0, 27, 0, 19, 10, 27, 0,216, 9, 4, 0, 16, 0, 7, 0, 47, 10, 7, 0, 48, 10, 7, 0, 49, 10, 7, 0, 50, 10, - 7, 0, 51, 10, 7, 0, 52, 10, 7, 0, 53, 10, 7, 0, 54, 10, 7, 0, 55, 10, 2, 0, 18, 0, 2, 0, 27, 0, 2, 0, 91, 0, - 2, 0, 30, 0,128, 1, 3, 0, 27, 0, 19, 10, 4, 0, 18, 0, 4, 0, 31, 2,129, 1, 5, 0, 27, 0, 19, 10, 4, 0, 18, 0, - 4, 0, 27, 0, 7, 0, 56, 10, 0, 0, 11, 3,130, 1, 10, 0, 27, 0, 19, 10, 0, 0, 11, 3, 2, 0, 57, 10, 2, 0, 58, 10, - 0, 0, 59, 10, 0, 0, 60, 10, 7, 0, 61, 10, 7, 0, 62, 10, 7, 0, 63, 10, 7, 0, 64, 10,131, 1, 5, 0, 27, 0, 19, 10, - 0, 0, 11, 3, 7, 0,220, 2, 2, 0, 65, 10, 2, 0, 18, 0,132, 1, 8, 0, 7, 0, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, - 7, 0, 11, 0, 7, 0, 66, 10, 7, 0, 67, 10, 2, 0, 18, 0, 2, 0, 31, 2,133, 1, 8, 0, 7, 0, 8, 0, 7, 0, 9, 0, - 7, 0, 10, 0, 7, 0, 11, 0, 7, 0, 66, 10, 7, 0, 67, 10, 2, 0, 18, 0, 2, 0, 31, 2,134, 1, 8, 0, 7, 0, 8, 0, - 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11, 0, 7, 0, 66, 10, 7, 0, 67, 10, 2, 0, 18, 0, 2, 0, 31, 2,135, 1, 7, 0, - 27, 0, 19, 10, 0, 0, 11, 3, 7, 0, 94, 1, 7, 0,103, 1, 2, 0, 18, 0, 2, 0, 87, 1, 4, 0, 27, 0,136, 1, 5, 0, - 27, 0, 70, 3, 7, 0, 94, 1, 2, 0, 74, 3, 0, 0, 76, 3, 0, 0, 68, 10,137, 1, 7, 0,229, 0,106, 6, 0, 0, 69, 10, - 4, 0, 18, 0, 4, 0, 27, 0, 0, 0, 70, 10, 27, 0,208, 5, 27, 0, 71, 10,138, 1, 3, 0,229, 0,106, 6, 4, 0, 18, 0, - 4, 0, 27, 0,139, 1, 6, 0,229, 0,106, 6, 4, 0, 18, 0, 4, 0, 27, 0, 0, 0, 70, 10, 7, 0, 56, 10, 27, 0,208, 5, -140, 1, 10, 0,140, 1, 0, 0,140, 1, 1, 0, 2, 0, 16, 0, 2, 0, 18, 0, 0, 0, 72, 10, 7, 0, 31, 1, 7, 0, 32, 1, - 2, 0,253, 9, 2, 0, 73, 10, 27, 0, 44, 0,141, 1, 22, 0,141, 1, 0, 0,141, 1, 1, 0, 2, 0, 18, 0, 2, 0, 87, 1, - 2, 0, 74, 10, 2, 0, 75, 10, 31, 0, 80, 0,176, 0, 86, 9, 27, 0,168, 0, 7, 0, 89, 0, 7, 0, 90, 0, 7, 0, 76, 10, - 7, 0, 77, 10, 7, 0, 78, 10, 7, 0, 79, 10, 7, 0,253, 2, 7, 0,148, 3, 7, 0, 88, 9, 7, 0, 80, 10, 0, 0, 81, 10, - 0, 0, 82, 10, 14, 0,188, 3,142, 1, 11, 0, 7, 0, 46, 2, 7, 0,116, 9, 7, 0,117, 9, 11, 0, 2, 0, 2, 0, 83, 10, - 2, 0, 84, 10, 2, 0, 85, 10, 2, 0, 86, 10, 2, 0, 87, 10, 2, 0, 88, 10, 2, 0,181, 2,143, 1, 21, 0,143, 1, 0, 0, -143, 1, 1, 0,143, 1, 89, 10, 0, 0, 19, 0, 11, 0, 90, 10, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 91, 10, 2, 0, 92, 10, - 7, 0, 93, 10, 7, 0, 94, 10, 11, 0, 95, 10, 2, 0, 96, 10, 2, 0, 97, 10, 4, 0, 74, 0, 11, 0,150, 9, 4, 0, 98, 10, - 4, 0, 99, 10,143, 1,100, 10,144, 1,101, 10,142, 1,102, 10,145, 1, 4, 0, 0, 0,103, 10, 2, 0,104, 10, 2, 0,105, 10, - 4, 0, 27, 0,146, 1, 37, 0,146, 1, 0, 0,146, 1, 1, 0,146, 1,106, 10, 0, 0, 19, 0, 2, 0, 16, 0, 2, 0, 18, 0, - 2, 0,197, 8, 2, 0,176, 2, 2, 0,107, 10, 2, 0, 9, 7, 2, 0, 96, 10, 2, 0, 40, 9, 14, 0, 81, 9, 14, 0,108, 10, -146, 1, 38, 0, 22, 0, 42, 7, 11, 0, 90, 10, 7, 0, 93, 10, 7, 0, 94, 10, 7, 0, 81, 2, 7, 0, 1, 3, 7, 0,109, 10, - 4, 0,110, 10, 0, 0,111, 10, 2, 0,112, 10, 2, 0,113, 10, 7, 0,114, 10, 7, 0,115, 10, 2, 0,116, 10, 2, 0,117, 10, - 11, 0,118, 10, 19, 0,119, 10, 19, 0,120, 10, 19, 0,121, 10,145, 1,154, 0,147, 1,122, 10,148, 1,123, 10,144, 1, 8, 0, -144, 1, 0, 0,144, 1, 1, 0,146, 1,124, 10,146, 1,125, 10,143, 1,126, 10,143, 1,127, 10, 4, 0, 18, 0, 4, 0, 27, 0, - 57, 0, 20, 0, 22, 0, 32, 0, 34, 0, 75, 0,178, 0,182, 3, 14, 0,128, 10, 14, 0,129, 10, 4, 0, 16, 0, 4, 0,130, 10, - 4, 0,131, 10, 4, 0, 18, 0, 4, 0,110, 10, 4, 0,132, 10, 14, 0, 81, 9, 14, 0,108, 10,149, 1,133, 10, 11, 0,134, 10, - 11, 0,135, 10, 4, 0,136, 10, 11, 0,137, 10, 11, 0,138, 10, 11, 0,139, 10,150, 1, 4, 0, 4, 0, 17, 0, 4, 0,230, 2, - 4, 0,116, 9, 4, 0,117, 9,151, 1, 4, 0, 4, 0, 17, 0, 7, 0,230, 2, 7, 0,116, 9, 7, 0,117, 9,152, 1, 2, 0, - 0, 0,230, 2, 0, 0, 86, 1,153, 1, 4, 0, 4, 0, 17, 0, 7, 0,140, 10, 7, 0,116, 9, 7, 0,117, 9,154, 1, 1, 0, - 7, 0,141, 10,155, 1, 6, 0, 4, 0,127, 0, 4, 0,129, 0, 4, 0, 40, 9, 0, 0,142, 10, 0, 0,143, 10, 2, 0, 27, 0, -156, 1, 16, 0, 2, 0,141, 8, 2, 0,142, 8, 2, 0,144, 10, 2, 0,145, 10, 2, 0,146, 10, 2, 0, 67, 0, 2, 0, 43, 7, - 2, 0,147, 10, 7, 0,252, 2, 7, 0,148, 10, 7, 0,149, 10, 2, 0,109, 1, 0, 0,150, 10, 0, 0,151, 10, 4, 0,152, 10, - 4, 0,153, 10,157, 1, 9, 0, 7, 0,154, 10, 7, 0,155, 10, 7, 0,149, 9, 7, 0, 94, 3, 7, 0,156, 10, 7, 0,218, 6, - 2, 0, 92, 3, 0, 0,157, 10, 0, 0, 27, 0,158, 1, 4, 0, 7, 0,158, 10, 7, 0,159, 10, 2, 0, 92, 3, 2, 0, 27, 0, -159, 1, 3, 0, 7, 0,160, 10, 7, 0,212, 8, 7, 0, 14, 0,160, 1, 4, 0, 0, 0, 35, 0,204, 0, 80, 5, 4, 0,129, 0, - 4, 0,132, 4,161, 1, 6, 0, 0, 0,161, 10,204, 0,162, 10, 4, 0,129, 0, 4, 0,132, 4, 4, 0,163, 10, 4, 0, 27, 0, -162, 1, 4, 0, 2, 0,164, 10, 2, 0,165, 10, 4, 0, 30, 0,204, 0,162, 10,163, 1, 9, 0, 7, 0,166, 10, 7, 0,167, 10, - 7, 0,168, 10, 7, 0, 92, 2, 7, 0,169, 10, 7, 0,170, 10, 7, 0,171, 10, 2, 0,172, 10, 2, 0,173, 10,164, 1, 8, 0, - 2, 0,174, 10, 2, 0,175, 10, 2, 0,176, 10, 2, 0,177, 10, 7, 0,178, 10, 7, 0,179, 10, 7, 0,180, 10, 7, 0,181, 10, -165, 1, 2, 0, 7, 0, 5, 0, 7, 0, 6, 0,166, 1, 2, 0, 0, 0,170, 0, 0, 0,182, 10,167, 1, 1, 0, 0, 0, 19, 0, -168, 1, 12, 0, 0, 0,183, 10, 0, 0,184, 10, 0, 0,209, 6, 0, 0,185, 10, 2, 0,144, 10, 2, 0,186, 10, 7, 0,187, 10, - 7, 0,188, 10, 7, 0,189, 10, 7, 0,148, 3, 7, 0,190, 10, 7, 0,191, 10,169, 1, 2, 0, 11, 0,192, 10, 11, 0,193, 10, -170, 1, 13, 0, 0, 0, 72, 5, 0, 0, 16, 0, 0, 0, 92, 3, 0, 0, 94, 3, 0, 0,184, 10, 0, 0,108, 0, 0, 0,181, 2, - 7, 0,194, 10, 7, 0,195, 10, 7, 0,147, 3, 7, 0,196, 10, 7, 0,197, 10, 7, 0,191, 10,171, 1, 8, 0, 7, 0, 47, 9, - 7, 0,128, 0, 7, 0,151, 10, 7, 0,172, 2, 7, 0,198, 10, 7, 0,240, 0, 7, 0,199, 10, 4, 0, 16, 0,172, 1, 4, 0, - 2, 0,200, 10, 2, 0,201, 10, 2, 0,202, 10, 2, 0, 27, 0,173, 1, 8, 0, 7, 0,203, 10, 7, 0,220, 2, 7, 0,204, 10, - 7, 0,190, 8, 7, 0,191, 8, 7, 0,192, 8, 7, 0,205, 10, 7, 0,206, 10,174, 1, 6, 0, 2, 0,207, 10, 2, 0,208, 10, - 7, 0,209, 10, 7, 0,210, 10, 7, 0,211, 10, 7, 0,212, 10,175, 1, 2, 0, 58, 0,213, 10, 59, 0,214, 10,176, 1, 3, 0, -175, 1, 79, 6, 7, 0,215, 10, 7, 0,216, 10,177, 1, 3, 0,175, 1, 79, 6, 4, 0,217, 10, 4, 0, 27, 0,178, 1, 1, 0, -175, 1, 79, 6,179, 1, 3, 0,175, 1, 79, 6, 4, 0,217, 10, 4, 0,218, 10,180, 1, 3, 0,175, 1, 79, 6, 4, 0,219, 10, - 4, 0, 27, 0,181, 1, 1, 0,175, 1, 79, 6,182, 1, 3, 0,175, 1, 79, 6, 4, 0,220, 10, 4, 0, 27, 0,183, 1, 3, 0, -175, 1, 79, 6, 4, 0,221, 10, 4, 0, 27, 0,184, 1, 3, 0,175, 1, 79, 6, 4, 0,222, 10, 4, 0, 27, 0,185, 1, 3, 0, +240, 0,200, 6,176, 0,179, 3,243, 0, 10, 10, 0, 0, 87, 1, 0, 0,203, 6, 2, 0, 18, 0, 7, 0, 11, 10,108, 1, 8, 0, +108, 1, 0, 0,108, 1, 1, 0,106, 1, 12, 10, 31, 0, 80, 0, 14, 0,185, 3, 4, 0, 18, 0, 0, 0, 19, 0, 4, 0,118, 8, +109, 1, 5, 0,109, 1, 0, 0,109, 1, 1, 0, 31, 0, 80, 0, 2, 0, 18, 0, 0, 0, 13, 10,110, 1, 14, 0,110, 1, 0, 0, +110, 1, 1, 0, 11, 0, 2, 0, 2, 0, 16, 0, 2, 0, 18, 0, 0, 0, 14, 10, 0, 0, 15, 10, 0, 0, 19, 0, 2, 0, 27, 0, + 7, 0, 16, 10, 7, 0, 17, 10, 31, 0, 80, 0, 7, 0, 18, 10, 7, 0, 19, 10,111, 1, 9, 0,111, 1, 0, 0,111, 1, 1, 0, + 27, 0, 20, 10, 0, 0, 11, 3, 7, 0, 21, 10, 2, 0, 22, 10, 2, 0, 18, 0, 2, 0, 16, 0, 2, 0, 23, 10,112, 1, 7, 0, + 37, 0, 6, 7, 21, 0,157, 9, 4, 0, 18, 0, 4, 0, 24, 10, 14, 0, 25, 10, 27, 0, 20, 10, 0, 0, 11, 3,113, 1, 15, 0, + 27, 0, 20, 10, 2, 0, 26, 10, 2, 0, 18, 0, 2, 0, 27, 10, 2, 0, 28, 10, 0, 0, 11, 3, 27, 0, 29, 10, 0, 0, 30, 10, + 7, 0, 31, 10, 7, 0, 40, 2, 7, 0, 32, 10, 7, 0, 33, 10, 2, 0, 16, 0, 2, 0, 87, 1, 7, 0, 94, 1,114, 1, 6, 0, + 27, 0, 20, 10, 7, 0,193, 9, 2, 0, 34, 10, 2, 0, 35, 10, 2, 0, 18, 0, 2, 0, 36, 10,115, 1, 6, 0, 27, 0, 20, 10, + 4, 0, 37, 10, 4, 0, 38, 10, 4, 0, 92, 0, 4, 0, 27, 0, 0, 0, 11, 3,116, 1, 4, 0, 27, 0, 20, 10, 4, 0, 18, 0, + 4, 0, 37, 10, 0, 0, 11, 3,117, 1, 4, 0, 27, 0, 20, 10, 4, 0, 18, 0, 4, 0, 37, 10, 0, 0, 11, 3,118, 1, 4, 0, + 27, 0, 20, 10, 4, 0, 18, 0, 4, 0, 37, 10, 0, 0, 11, 3,119, 1, 2, 0, 4, 0, 18, 0, 7, 0, 84, 4,120, 1, 2, 0, + 27, 0, 20, 10, 0, 0, 11, 3,121, 1, 10, 0, 27, 0, 20, 10, 4, 0, 39, 10, 7, 0,128, 0, 4, 0, 18, 0, 2, 0, 4, 7, + 2, 0, 40, 10, 2, 0, 67, 0, 2, 0, 30, 0, 7, 0, 41, 10, 0, 0, 11, 3,122, 1, 10, 0, 27, 0, 20, 10, 2, 0, 16, 0, + 2, 0,134, 4, 4, 0, 90, 0, 4, 0, 91, 0, 7, 0,117, 9, 7, 0,118, 9, 4, 0, 27, 0,176, 0, 87, 9, 0, 0, 11, 3, +123, 1, 4, 0, 27, 0, 20, 10, 4, 0,210, 3, 4, 0, 42, 10, 0, 0, 11, 3,124, 1, 4, 0, 27, 0, 20, 10, 4, 0,210, 3, + 4, 0, 27, 0, 0, 0, 11, 3,125, 1, 6, 0, 27, 0, 20, 10, 7, 0,128, 0, 7, 0, 82, 3, 4, 0, 43, 10, 2, 0,210, 3, + 2, 0,211, 3,126, 1, 6, 0, 27, 0, 20, 10, 4, 0, 44, 10, 4, 0, 45, 10, 7, 0, 46, 10, 7, 0, 47, 10, 0, 0, 11, 3, +127, 1, 16, 0, 27, 0, 20, 10, 27, 0,217, 9, 4, 0, 16, 0, 7, 0, 48, 10, 7, 0, 49, 10, 7, 0, 50, 10, 7, 0, 51, 10, + 7, 0, 52, 10, 7, 0, 53, 10, 7, 0, 54, 10, 7, 0, 55, 10, 7, 0, 56, 10, 2, 0, 18, 0, 2, 0, 27, 0, 2, 0, 67, 0, + 2, 0, 30, 0,128, 1, 3, 0, 27, 0, 20, 10, 4, 0, 18, 0, 4, 0, 32, 2,129, 1, 5, 0, 27, 0, 20, 10, 4, 0, 18, 0, + 4, 0, 27, 0, 7, 0, 57, 10, 0, 0, 11, 3,130, 1, 10, 0, 27, 0, 20, 10, 0, 0, 11, 3, 2, 0, 58, 10, 2, 0, 59, 10, + 0, 0, 60, 10, 0, 0, 61, 10, 7, 0, 62, 10, 7, 0, 63, 10, 7, 0, 64, 10, 7, 0, 65, 10,131, 1, 5, 0, 27, 0, 20, 10, + 0, 0, 11, 3, 7, 0,220, 2, 2, 0, 66, 10, 2, 0, 18, 0,132, 1, 8, 0, 7, 0, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, + 7, 0, 11, 0, 7, 0, 67, 10, 7, 0, 68, 10, 2, 0, 18, 0, 2, 0, 32, 2,133, 1, 8, 0, 7, 0, 8, 0, 7, 0, 9, 0, + 7, 0, 10, 0, 7, 0, 11, 0, 7, 0, 67, 10, 7, 0, 68, 10, 2, 0, 18, 0, 2, 0, 32, 2,134, 1, 8, 0, 7, 0, 8, 0, + 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11, 0, 7, 0, 67, 10, 7, 0, 68, 10, 2, 0, 18, 0, 2, 0, 32, 2,135, 1, 7, 0, + 27, 0, 20, 10, 0, 0, 11, 3, 7, 0, 94, 1, 7, 0,103, 1, 2, 0, 18, 0, 2, 0, 87, 1, 4, 0, 27, 0,136, 1, 5, 0, + 27, 0, 70, 3, 7, 0, 94, 1, 2, 0, 74, 3, 0, 0, 76, 3, 0, 0, 69, 10,137, 1, 7, 0,229, 0,106, 6, 0, 0, 70, 10, + 4, 0, 18, 0, 4, 0, 27, 0, 0, 0, 71, 10, 27, 0,208, 5, 27, 0, 72, 10,138, 1, 3, 0,229, 0,106, 6, 4, 0, 18, 0, + 4, 0, 27, 0,139, 1, 6, 0,229, 0,106, 6, 4, 0, 18, 0, 4, 0, 27, 0, 0, 0, 71, 10, 7, 0, 57, 10, 27, 0,208, 5, +140, 1, 10, 0,140, 1, 0, 0,140, 1, 1, 0, 2, 0, 16, 0, 2, 0, 18, 0, 0, 0, 73, 10, 7, 0, 31, 1, 7, 0, 32, 1, + 2, 0,254, 9, 2, 0, 74, 10, 27, 0, 44, 0,141, 1, 22, 0,141, 1, 0, 0,141, 1, 1, 0, 2, 0, 18, 0, 2, 0, 87, 1, + 2, 0, 75, 10, 2, 0, 76, 10, 31, 0, 80, 0,176, 0, 87, 9, 27, 0,168, 0, 7, 0, 90, 0, 7, 0, 91, 0, 7, 0, 77, 10, + 7, 0, 78, 10, 7, 0, 79, 10, 7, 0, 80, 10, 7, 0,253, 2, 7, 0,148, 3, 7, 0, 89, 9, 7, 0, 81, 10, 0, 0, 82, 10, + 0, 0, 83, 10, 14, 0,188, 3,142, 1, 11, 0, 7, 0, 47, 2, 7, 0,117, 9, 7, 0,118, 9, 11, 0, 2, 0, 2, 0, 84, 10, + 2, 0, 85, 10, 2, 0, 86, 10, 2, 0, 87, 10, 2, 0, 88, 10, 2, 0, 89, 10, 2, 0,181, 2,143, 1, 21, 0,143, 1, 0, 0, +143, 1, 1, 0,143, 1, 90, 10, 0, 0, 19, 0, 11, 0, 91, 10, 2, 0, 16, 0, 2, 0, 18, 0, 2, 0, 92, 10, 2, 0, 93, 10, + 7, 0, 94, 10, 7, 0, 95, 10, 11, 0, 96, 10, 2, 0, 97, 10, 2, 0, 98, 10, 4, 0,247, 1, 11, 0,151, 9, 4, 0, 99, 10, + 4, 0,100, 10,143, 1,101, 10,144, 1,102, 10,142, 1,103, 10,145, 1, 4, 0, 0, 0,104, 10, 2, 0,105, 10, 2, 0,106, 10, + 4, 0, 27, 0,146, 1, 37, 0,146, 1, 0, 0,146, 1, 1, 0,146, 1,107, 10, 0, 0, 19, 0, 2, 0, 16, 0, 2, 0, 18, 0, + 2, 0,198, 8, 2, 0,176, 2, 2, 0,108, 10, 2, 0, 9, 7, 2, 0, 97, 10, 2, 0, 41, 9, 14, 0, 82, 9, 14, 0,109, 10, +146, 1, 38, 0, 22, 0, 42, 7, 11, 0, 91, 10, 7, 0, 94, 10, 7, 0, 95, 10, 7, 0, 82, 2, 7, 0, 1, 3, 7, 0,110, 10, + 4, 0,111, 10, 0, 0,112, 10, 2, 0,113, 10, 2, 0,114, 10, 7, 0,115, 10, 7, 0,116, 10, 2, 0,117, 10, 2, 0,118, 10, + 11, 0,119, 10, 19, 0,120, 10, 19, 0,121, 10, 19, 0,122, 10,145, 1,154, 0,147, 1,123, 10,148, 1,124, 10,144, 1, 8, 0, +144, 1, 0, 0,144, 1, 1, 0,146, 1,125, 10,146, 1,126, 10,143, 1,127, 10,143, 1,128, 10, 4, 0, 18, 0, 4, 0, 27, 0, + 57, 0, 20, 0, 22, 0, 32, 0, 34, 0, 75, 0,178, 0,182, 3, 14, 0,129, 10, 14, 0,130, 10, 4, 0, 16, 0, 4, 0,131, 10, + 4, 0,132, 10, 4, 0, 18, 0, 4, 0,111, 10, 4, 0,133, 10, 14, 0, 82, 9, 14, 0,109, 10,149, 1,134, 10, 11, 0,135, 10, + 11, 0,136, 10, 4, 0,137, 10, 11, 0,138, 10, 11, 0,139, 10, 11, 0,140, 10,150, 1, 4, 0, 4, 0, 17, 0, 4, 0,230, 2, + 4, 0,117, 9, 4, 0,118, 9,151, 1, 4, 0, 4, 0, 17, 0, 7, 0,230, 2, 7, 0,117, 9, 7, 0,118, 9,152, 1, 2, 0, + 0, 0,230, 2, 0, 0, 86, 1,153, 1, 4, 0, 4, 0, 17, 0, 7, 0,141, 10, 7, 0,117, 9, 7, 0,118, 9,154, 1, 1, 0, + 7, 0,142, 10,155, 1, 6, 0, 4, 0,127, 0, 4, 0,129, 0, 4, 0, 41, 9, 0, 0,143, 10, 0, 0,144, 10, 2, 0, 27, 0, +156, 1, 16, 0, 2, 0,141, 8, 2, 0,142, 8, 2, 0,145, 10, 2, 0,146, 10, 2, 0,147, 10, 2, 0, 68, 0, 2, 0, 43, 7, + 2, 0,148, 10, 7, 0,252, 2, 7, 0,149, 10, 7, 0,150, 10, 2, 0,109, 1, 0, 0,151, 10, 0, 0,152, 10, 4, 0,153, 10, + 4, 0,154, 10,157, 1, 9, 0, 7, 0,155, 10, 7, 0,156, 10, 7, 0,150, 9, 7, 0, 94, 3, 7, 0,157, 10, 7, 0,218, 6, + 2, 0, 92, 3, 0, 0,158, 10, 0, 0, 27, 0,158, 1, 4, 0, 7, 0,159, 10, 7, 0,160, 10, 2, 0, 92, 3, 2, 0, 27, 0, +159, 1, 3, 0, 7, 0,161, 10, 7, 0,213, 8, 7, 0, 14, 0,160, 1, 4, 0, 0, 0, 35, 0,204, 0, 80, 5, 4, 0,129, 0, + 4, 0,132, 4,161, 1, 6, 0, 0, 0,162, 10,204, 0,163, 10, 4, 0,129, 0, 4, 0,132, 4, 4, 0,164, 10, 4, 0, 27, 0, +162, 1, 4, 0, 2, 0,165, 10, 2, 0,166, 10, 4, 0, 30, 0,204, 0,163, 10,163, 1, 9, 0, 7, 0,167, 10, 7, 0,168, 10, + 7, 0,169, 10, 7, 0, 93, 2, 7, 0,170, 10, 7, 0,171, 10, 7, 0,172, 10, 2, 0,173, 10, 2, 0,174, 10,164, 1, 8, 0, + 2, 0,175, 10, 2, 0,176, 10, 2, 0,177, 10, 2, 0,178, 10, 7, 0,179, 10, 7, 0,180, 10, 7, 0,181, 10, 7, 0,182, 10, +165, 1, 2, 0, 7, 0, 5, 0, 7, 0, 6, 0,166, 1, 2, 0, 0, 0,170, 0, 0, 0,183, 10,167, 1, 1, 0, 0, 0, 19, 0, +168, 1, 12, 0, 0, 0,184, 10, 0, 0,185, 10, 0, 0,209, 6, 0, 0,186, 10, 2, 0,145, 10, 2, 0,187, 10, 7, 0,188, 10, + 7, 0,189, 10, 7, 0,190, 10, 7, 0,148, 3, 7, 0,191, 10, 7, 0,192, 10,169, 1, 2, 0, 11, 0,193, 10, 11, 0,194, 10, +170, 1, 13, 0, 0, 0, 72, 5, 0, 0, 16, 0, 0, 0, 92, 3, 0, 0, 94, 3, 0, 0,185, 10, 0, 0,108, 0, 0, 0,181, 2, + 7, 0,195, 10, 7, 0,196, 10, 7, 0,147, 3, 7, 0,197, 10, 7, 0,198, 10, 7, 0,192, 10,171, 1, 8, 0, 7, 0, 48, 9, + 7, 0,128, 0, 7, 0,152, 10, 7, 0,172, 2, 7, 0,199, 10, 7, 0,240, 0, 7, 0,200, 10, 4, 0, 16, 0,172, 1, 4, 0, + 2, 0,201, 10, 2, 0,202, 10, 2, 0,203, 10, 2, 0, 27, 0,173, 1, 8, 0, 7, 0,204, 10, 7, 0,220, 2, 7, 0,205, 10, + 7, 0,191, 8, 7, 0,192, 8, 7, 0,193, 8, 7, 0,206, 10, 7, 0,207, 10,174, 1, 6, 0, 2, 0,208, 10, 2, 0,209, 10, + 7, 0,210, 10, 7, 0,211, 10, 7, 0,212, 10, 7, 0,213, 10,175, 1, 2, 0, 58, 0,214, 10, 59, 0,215, 10,176, 1, 3, 0, +175, 1, 79, 6, 7, 0,216, 10, 7, 0,217, 10,177, 1, 3, 0,175, 1, 79, 6, 4, 0,218, 10, 4, 0, 27, 0,178, 1, 1, 0, +175, 1, 79, 6,179, 1, 3, 0,175, 1, 79, 6, 4, 0,218, 10, 4, 0,219, 10,180, 1, 3, 0,175, 1, 79, 6, 4, 0,220, 10, + 4, 0, 27, 0,181, 1, 1, 0,175, 1, 79, 6,182, 1, 3, 0,175, 1, 79, 6, 4, 0,221, 10, 4, 0, 27, 0,183, 1, 3, 0, +175, 1, 79, 6, 4, 0,222, 10, 4, 0, 27, 0,184, 1, 3, 0,175, 1, 79, 6, 4, 0,223, 10, 4, 0, 27, 0,185, 1, 3, 0, 175, 1, 79, 6, 4, 0,250, 0, 4, 0, 27, 0,186, 1, 1, 0, 0, 0, 19, 0,187, 1, 1, 0, 0, 0, 19, 0,188, 1, 4, 0, - 7, 0, 5, 0, 7, 0, 6, 0, 2, 0, 18, 0, 2, 0,223, 10,189, 1, 10, 0, 2, 0, 62, 4, 2, 0, 18, 0, 7, 0,217, 4, - 7, 0,224, 10, 7, 0,225, 10, 7, 0,226, 10, 7, 0,227, 10,188, 1,228, 10,188, 1,229, 10,188, 1,230, 10, 54, 0, 11, 0, - 4, 0, 18, 0, 4, 0, 63, 0, 4, 0,231, 10, 4, 0,232, 10, 19, 0,233, 10, 19, 0,234, 10,189, 1,235, 10, 7, 0,236, 10, - 7, 0,237, 10, 7, 0,238, 10, 7, 0,239, 10, 0, 1, 10, 0, 4, 0,253, 9, 4, 0,240, 10, 7, 0,241, 10, 7, 0,242, 10, - 7, 0,243, 10, 7, 0,244, 10, 7, 0, 9, 0, 7, 0, 11, 0, 4, 0, 87, 1, 4, 0, 1, 3,255, 0, 18, 0, 4, 0,132, 0, - 4, 0,245, 10, 4, 0,246, 10, 7, 0,247, 10, 4, 0,248, 10, 7, 0,249, 10, 7, 0,250, 10, 4, 0,251, 10, 7, 0,252, 10, - 4, 0,253, 10, 7, 0,254, 10, 0, 1,255, 10, 7, 0, 0, 11, 7, 0, 1, 11, 7, 0, 2, 11, 7, 0, 3, 11, 4, 0, 4, 11, - 4, 0, 27, 0,190, 1, 4, 0, 42, 0,244, 2, 7, 0, 5, 11, 7, 0,178, 1, 7, 0, 27, 0,213, 0, 34, 0, 22, 0, 32, 0, -190, 1, 6, 11, 54, 0,228, 10, 46, 0, 7, 11, 52, 0, 8, 11, 25, 0,154, 0, 0, 0, 9, 11, 7, 0, 10, 11, 2, 0,109, 6, - 2, 0, 11, 11, 4, 0,108, 0, 4, 0, 18, 0, 7, 0, 12, 11, 4, 0, 89, 2, 4, 0, 13, 11, 7, 0, 14, 11, 7, 0, 15, 11, - 7, 0, 16, 11, 7, 0,178, 1, 4, 0, 17, 11, 7, 0, 18, 11, 0, 0, 19, 11, 0, 0, 20, 11, 0, 0, 21, 11, 0, 0, 22, 11, - 7, 0, 23, 11, 7, 0, 24, 11, 7, 0, 25, 11, 7, 0, 1, 3, 7, 0, 26, 11, 4, 0, 27, 11, 7, 0,240, 5, 7, 0, 28, 11, - 7, 0, 29, 11,191, 1, 10, 0, 4, 0, 16, 0, 4, 0,128, 0, 4, 0, 18, 0, 4, 0, 15, 4, 4, 0, 30, 11, 4, 0, 31, 11, - 4, 0, 32, 11, 4, 0, 73, 0, 0, 0, 19, 0, 11, 0, 2, 0,192, 1, 1, 0, 0, 0, 70, 7, 95, 0, 8, 0,191, 1, 33, 11, - 4, 0, 34, 11, 4, 0, 35, 11, 4, 0, 36, 11, 4, 0, 37, 11, 4, 0, 30, 0, 11, 0, 38, 11,192, 1, 39, 11,193, 1, 5, 0, - 7, 0,165, 2, 7, 0,240, 2, 7, 0, 39, 2, 2, 0,147, 2, 2, 0, 27, 0,194, 1, 5, 0, 7, 0,165, 2, 7, 0,159, 4, - 7, 0, 40, 11, 7, 0, 41, 11, 7, 0,240, 2,195, 1, 5, 0, 27, 0, 42, 11,196, 1, 21, 0, 7, 0, 75, 6, 7, 0, 43, 11, - 7, 0, 56, 0,197, 1, 3, 0, 7, 0, 44, 11, 4, 0, 45, 11, 4, 0, 46, 11,198, 1, 7, 0, 4, 0, 47, 11, 4, 0, 48, 11, - 4, 0, 49, 11, 7, 0, 50, 11, 7, 0, 51, 11, 7, 0, 52, 11, 7, 0, 56, 0,199, 1, 8, 0,199, 1, 0, 0,199, 1, 1, 0, - 27, 0, 44, 0, 4, 0, 3, 1, 2, 0, 18, 0, 2, 0, 87, 1, 7, 0,240, 2, 7, 0, 55, 9,200, 1, 7, 0,200, 1, 0, 0, -200, 1, 1, 0, 27, 0, 44, 0, 2, 0,225, 2, 2, 0, 18, 0, 2, 0, 13, 2, 2, 0, 56, 0,201, 1, 17, 0,194, 1, 8, 4, -194, 1, 53, 11,193, 1, 54, 11,194, 1, 38, 9,195, 1, 55, 11, 4, 0, 82, 0, 7, 0,240, 2, 7, 0, 7, 3, 7, 0, 56, 11, - 4, 0, 47, 11, 4, 0, 57, 11, 7, 0, 51, 11, 7, 0, 52, 11, 7, 0,108, 0, 4, 0, 58, 11, 2, 0, 18, 0, 2, 0, 59, 11, -202, 1, 15, 0, 7, 0,255, 0, 7, 0, 60, 11, 7, 0, 44, 11, 7, 0, 61, 11, 7, 0, 62, 11, 7, 0, 63, 11, 7, 0, 64, 11, - 7, 0, 65, 11, 7, 0, 66, 11, 7, 0, 67, 11, 7, 0, 68, 11, 7, 0, 69, 11, 7, 0, 70, 11, 4, 0, 18, 0, 4, 0, 71, 11, -203, 1,128, 0, 22, 0, 32, 0, 34, 0, 75, 0,204, 1, 72, 11,202, 1, 73, 11,187, 0,154, 4, 4, 0, 18, 0, 4, 0, 56, 0, - 2, 0, 16, 0, 2, 0, 57, 10, 2, 0, 74, 11, 2, 0,122, 1, 2, 0, 75, 11, 2, 0,232, 3, 2, 0, 76, 11, 2, 0, 77, 11, - 2, 0, 78, 11, 2, 0, 79, 11, 2, 0, 80, 11, 2, 0, 81, 11, 2, 0, 82, 11, 2, 0, 83, 11, 2, 0, 84, 11, 2, 0,224, 5, - 2, 0, 85, 11, 2, 0, 86, 11, 2, 0, 87, 11, 2, 0, 88, 11, 2, 0, 89, 11, 2, 0, 28, 2, 2, 0, 31, 9, 2, 0, 6, 9, - 2, 0, 90, 11, 2, 0, 91, 11, 2, 0, 25, 4, 2, 0, 26, 4, 2, 0, 92, 11, 2, 0, 93, 11, 2, 0, 94, 11, 2, 0, 95, 11, - 7, 0, 96, 11, 7, 0, 97, 11, 7, 0, 98, 11, 7, 0, 99, 11, 7, 0,100, 11, 7, 0,101, 11, 7, 0,102, 11, 2, 0,154, 5, - 2, 0,103, 11, 7, 0,104, 11, 7, 0,105, 11, 7, 0,106, 11, 7, 0, 13, 9, 7, 0, 90, 0, 7, 0, 7, 3, 7, 0, 19, 9, - 7, 0,107, 11, 7, 0,108, 11, 7, 0,109, 11, 7, 0,110, 11, 7, 0,111, 11, 7, 0,112, 11, 4, 0, 14, 9, 4, 0, 12, 9, - 4, 0,113, 11, 4, 0,114, 11, 2, 0,115, 11, 2, 0,116, 11, 7, 0, 15, 9, 7, 0, 16, 9, 7, 0, 17, 9, 7, 0,117, 11, - 7, 0,118, 11, 7, 0,119, 11, 7, 0,120, 11, 7, 0,121, 11, 7, 0,122, 11, 7, 0,123, 11, 7, 0,124, 11, 7, 0,125, 11, - 7, 0,222, 3, 7, 0,108, 0, 7, 0,126, 11, 7, 0,127, 11, 7, 0,128, 11, 7, 0,129, 11, 7, 0,214, 0, 7, 0,130, 11, - 4, 0,131, 11, 4, 0,132, 11, 7, 0,133, 11, 7, 0,134, 11, 7, 0,135, 11, 7, 0,136, 11, 7, 0,137, 11, 7, 0,213, 0, - 7, 0,138, 11, 7, 0, 52, 4, 7, 0, 50, 4, 7, 0, 51, 4, 7, 0,139, 11, 7, 0,140, 11, 7, 0,141, 11, 7, 0,142, 11, - 7, 0,143, 11, 7, 0,144, 11, 7, 0,145, 11, 7, 0,146, 11, 7, 0,147, 11, 7, 0,148, 11, 7, 0,149, 11, 7, 0,150, 11, - 7, 0,151, 11, 7, 0,152, 11, 7, 0,153, 11, 7, 0,154, 11, 7, 0,155, 11, 7, 0,156, 11, 4, 0,157, 11, 4, 0,158, 11, - 46, 0,140, 1, 64, 0, 0, 4, 14, 0,159, 11, 64, 0,160, 11, 27, 0,161, 11, 27, 0,162, 11, 31, 0, 80, 0,182, 0, 73, 1, -182, 0,163, 11,150, 0, 52, 0,150, 0, 0, 0,150, 0, 1, 0,203, 1,164, 11,201, 1,165, 11,198, 1,216, 9,190, 0, 80, 4, - 11, 0, 81, 4,205, 1,166, 11,205, 1,167, 11, 14, 0,168, 11, 14, 0,169, 11,135, 0,170, 11,143, 0,171, 11,143, 0,172, 11, - 27, 0,173, 11, 27, 0,174, 11, 27, 0, 38, 0, 14, 0, 24, 10, 0, 0, 19, 0, 7, 0,244, 0, 7, 0, 36, 3, 7, 0,175, 11, - 7, 0,176, 11, 4, 0,214, 2, 4, 0,177, 11, 4, 0, 18, 0, 4, 0, 14, 9, 4, 0,178, 11, 4, 0,179, 11, 4, 0,180, 11, - 4, 0,181, 11, 2, 0,251, 0, 2, 0,182, 11, 2, 0,183, 11, 2, 0,184, 11, 0, 0,185, 11, 2, 0,186, 11, 2, 0,187, 11, - 2, 0,188, 11, 11, 0,189, 11,139, 0,153, 4, 14, 0, 21, 3, 14, 0,190, 11,197, 1,191, 11, 4, 0,192, 11, 4, 0,193, 11, -206, 1,194, 11,141, 0, 33, 3,207, 1,195, 11, 7, 0,196, 11, 7, 0,197, 11, 7, 0,198, 11,137, 0, 38, 0,208, 1,150, 9, - 7, 0,123, 4, 7, 0,199, 11, 7, 0,200, 11, 7, 0, 75, 6, 7, 0,236, 3, 7, 0,222, 3, 7, 0,201, 11, 7, 0, 91, 2, - 7, 0,202, 11, 7, 0,203, 11, 7, 0,204, 11, 7, 0,205, 11, 7, 0,206, 11, 7, 0,207, 11, 7, 0,124, 4, 7, 0,208, 11, - 7, 0,209, 11, 7, 0,210, 11, 7, 0,125, 4, 7, 0,121, 4, 7, 0,122, 4, 7, 0,211, 11, 7, 0,212, 11, 7, 0,213, 11, - 4, 0,214, 11, 4, 0, 92, 0, 4, 0,215, 11, 4, 0,216, 11, 2, 0,217, 11, 2, 0,218, 11, 2, 0,219, 11, 2, 0,220, 11, - 2, 0,221, 11, 2, 0,222, 11, 2, 0,223, 11, 2, 0, 27, 0,187, 0,154, 4,138, 0, 11, 0,208, 1,224, 11, 7, 0,225, 11, - 7, 0,226, 11, 7, 0,250, 1, 7, 0,227, 11, 7, 0,228, 11, 7, 0,229, 11, 4, 0, 92, 0, 2, 0,230, 11, 2, 0,231, 11, - 64, 0,249, 1,209, 1, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 7, 0,232, 11,210, 1, 6, 0,210, 1, 0, 0, -210, 1, 1, 0,209, 1,192, 9, 4, 0, 1, 1, 2, 0,233, 11, 2, 0, 18, 0,211, 1, 5, 0,211, 1, 0, 0,211, 1, 1, 0, - 14, 0,234, 11, 4, 0,235, 11, 4, 0, 18, 0,212, 1, 9, 0,212, 1, 0, 0,212, 1, 1, 0, 14, 0,127, 0,211, 1,236, 11, - 4, 0, 18, 0, 2, 0,233, 11, 2, 0,237, 11, 7, 0, 93, 0, 0, 0,238, 11,178, 0, 6, 0, 22, 0, 32, 0, 14, 0,123, 5, - 4, 0, 18, 0, 2, 0,239, 11, 2, 0,240, 11, 11, 0,241, 11,213, 1, 6, 0, 14, 0,242, 11, 4, 0,243, 11, 4, 0,244, 11, - 4, 0, 18, 0, 4, 0, 27, 0,237, 0,245, 11,214, 1, 19, 0, 22, 0, 32, 0,215, 1,246, 11,215, 1,247, 11, 14, 0,248, 11, - 4, 0,249, 11, 2, 0,250, 11, 2, 0,251, 11, 14, 0,252, 11, 14, 0,253, 11,213, 1,254, 11, 14, 0,255, 11, 14, 0, 0, 12, - 14, 0, 1, 12, 14, 0, 2, 12,216, 1, 3, 12,216, 1, 4, 12,216, 1, 5, 12, 14, 0, 6, 12,237, 0, 7, 12,215, 1, 32, 0, -215, 1, 0, 0,215, 1, 1, 0, 11, 0, 8, 12, 4, 0,119, 8, 2, 0, 9, 12, 2, 0, 27, 0, 27, 1, 10, 12, 27, 1, 11, 12, - 0, 0, 12, 12, 2, 0, 13, 12, 2, 0, 14, 12, 2, 0,141, 8, 2, 0,142, 8, 2, 0, 15, 12, 2, 0, 16, 12, 2, 0, 15, 4, - 2, 0, 53, 7, 2, 0, 17, 12, 2, 0, 18, 12, 2, 0, 19, 12, 2, 0, 30, 0,217, 1, 20, 12,218, 1, 21, 12,219, 1, 22, 12, - 4, 0, 23, 12, 4, 0, 24, 12, 11, 0, 25, 12, 14, 0,253, 11, 14, 0,160, 8, 14, 0, 26, 12, 14, 0, 27, 12, 14, 0, 28, 12, -220, 1, 17, 0,220, 1, 0, 0,220, 1, 1, 0, 0, 0, 29, 12, 21, 0, 31, 0, 2, 0, 30, 12, 2, 0, 16, 0, 2, 0, 14, 0, - 2, 0, 31, 12, 2, 0, 32, 12, 2, 0, 33, 12, 2, 0, 34, 12, 2, 0, 35, 12, 2, 0, 18, 0, 2, 0, 36, 12, 2, 0, 32, 0, - 2, 0, 27, 0,221, 1, 37, 12,222, 1, 4, 0,222, 1, 0, 0,222, 1, 1, 0,220, 1, 38, 12,220, 1, 39, 12,223, 1, 11, 0, -223, 1, 0, 0,223, 1, 1, 0, 14, 0, 40, 12, 14, 0, 41, 12, 0, 0, 29, 12, 2, 0, 42, 12, 2, 0, 43, 12, 2, 0, 18, 0, - 2, 0, 44, 12, 4, 0, 45, 12, 11, 0, 46, 12,216, 1, 7, 0,216, 1, 0, 0,216, 1, 1, 0, 0, 0, 29, 12, 0, 0, 47, 12, - 14, 0, 59, 8, 4, 0, 48, 12, 4, 0, 18, 0,249, 0, 14, 0,249, 0, 0, 0,249, 0, 1, 0, 0, 0, 29, 12, 21, 0, 31, 0, -224, 1,135, 8, 11, 0, 49, 12, 11, 0, 50, 12,221, 1, 37, 12,213, 1, 51, 12, 14, 0, 52, 12,249, 0, 53, 12, 32, 1,239, 6, - 2, 0, 18, 0, 2, 0, 86, 1,225, 1, 12, 0,225, 1, 0, 0,225, 1, 1, 0, 11, 0, 2, 0, 11, 0, 54, 12, 0, 0, 19, 0, - 2, 0, 16, 0, 2, 0, 18, 0, 7, 0,138, 9, 7, 0,129, 0, 7, 0,132, 4, 7, 0, 88, 9, 7, 0, 80, 10,226, 1, 5, 0, - 7, 0, 55, 12, 4, 0, 56, 12, 4, 0, 57, 12, 4, 0, 87, 1, 4, 0, 18, 0,227, 1, 6, 0, 7, 0, 58, 12, 7, 0, 59, 12, - 7, 0, 60, 12, 7, 0, 61, 12, 4, 0, 16, 0, 4, 0, 18, 0,228, 1, 5, 0, 7, 0,116, 9, 7, 0,117, 9, 7, 0,240, 2, - 2, 0, 42, 2, 2, 0, 43, 2,229, 1, 5, 0,228, 1, 2, 0, 4, 0, 53, 0, 7, 0, 62, 12, 7, 0,116, 9, 7, 0,117, 9, -230, 1, 4, 0, 2, 0, 63, 12, 2, 0, 64, 12, 2, 0, 65, 12, 2, 0, 66, 12,231, 1, 2, 0, 37, 0, 37, 7, 21, 0,156, 9, -232, 1, 3, 0, 19, 0, 67, 12, 4, 0, 18, 0, 4, 0, 27, 0,233, 1, 6, 0, 7, 0,108, 0, 7, 0,209, 2, 7, 0, 68, 12, - 7, 0, 27, 0, 2, 0,250, 0, 2, 0, 69, 12,234, 1, 5, 0, 7, 0, 70, 12, 7, 0,128, 0, 7, 0,193, 9, 7, 0,194, 9, - 4, 0, 18, 0,235, 1, 6, 0, 22, 0, 42, 7, 0, 0, 71, 12, 0, 0, 72, 12, 2, 0, 73, 12, 2, 0, 18, 0, 4, 0, 74, 12, -236, 1, 7, 0,236, 1, 0, 0,236, 1, 1, 0, 0, 0, 19, 0,235, 1, 75, 12, 2, 0, 76, 12, 2, 0, 16, 0, 7, 0, 60, 0, -237, 1, 7, 0, 14, 0, 77, 12, 0, 0, 78, 12, 11, 0, 79, 12, 7, 0, 60, 0, 7, 0,138, 9, 4, 0, 16, 0, 4, 0, 18, 0, -238, 1, 3, 0, 7, 0, 80, 12, 4, 0, 18, 0, 4, 0, 27, 0,239, 1, 15, 0,239, 1, 0, 0,239, 1, 1, 0,106, 1, 11, 10, -237, 1, 61, 0, 14, 0,188, 3, 30, 0, 49, 0,238, 1, 81, 12, 4, 0, 53, 0, 7, 0, 60, 0, 2, 0, 18, 0, 2, 0, 22, 1, - 4, 0, 82, 12, 0, 0, 71, 12, 4, 0, 83, 12, 7, 0, 84, 12,240, 1, 2, 0, 0, 0, 85, 12, 0, 0, 86, 12,241, 1, 4, 0, -241, 1, 0, 0,241, 1, 1, 0,176, 0, 70, 3, 14, 0, 87, 12,242, 1, 25, 0,242, 1, 0, 0,242, 1, 1, 0, 14, 0, 88, 12, -176, 0, 86, 9,241, 1, 89, 12, 14, 0, 90, 12, 14, 0,188, 3, 0, 0, 19, 0, 7, 0,138, 9, 7, 0, 91, 12, 7, 0, 89, 0, - 7, 0, 90, 0, 7, 0, 76, 10, 7, 0, 77, 10, 7, 0,253, 2, 7, 0,148, 3, 7, 0, 88, 9, 7, 0, 80, 10, 2, 0, 92, 12, - 2, 0, 93, 12, 2, 0, 91, 0, 2, 0, 16, 0, 11, 0, 94, 12, 4, 0, 18, 0, 4, 0, 30, 0,243, 1, 6, 0,243, 1, 0, 0, -243, 1, 1, 0, 14, 0, 88, 12, 4, 0, 18, 0, 4, 0, 13, 2, 0, 0, 19, 0,244, 1, 11, 0,244, 1, 0, 0,244, 1, 1, 0, - 22, 0, 42, 7, 0, 0, 95, 12, 4, 0, 74, 12, 2, 0, 96, 12, 2, 0, 27, 0, 0, 0, 71, 12, 4, 0, 82, 12, 2, 0, 18, 0, - 2, 0, 97, 12,245, 1, 10, 0,245, 1, 0, 0,245, 1, 1, 0, 14, 0, 98, 12, 0, 0, 29, 12, 0, 0, 19, 0, 0, 0, 99, 12, - 0, 0,100, 12, 2, 0, 18, 0, 2, 0, 97, 12, 4, 0,101, 12,246, 1, 5, 0,246, 1, 0, 0,246, 1, 1, 0, 0, 0, 71, 12, - 4, 0, 82, 12, 7, 0,230, 2, 34, 0, 12, 0,176, 0,179, 3,176, 0,102, 12,241, 1, 89, 12, 14, 0,103, 12,242, 1,104, 12, - 14, 0,105, 12, 14, 0,106, 12, 4, 0, 18, 0, 4, 0,251, 0, 2, 0,107, 12, 2, 0,108, 12, 7, 0,109, 12,247, 1, 2, 0, + 7, 0, 5, 0, 7, 0, 6, 0, 2, 0, 18, 0, 2, 0,224, 10,189, 1, 10, 0, 2, 0, 62, 4, 2, 0, 18, 0, 7, 0,217, 4, + 7, 0,225, 10, 7, 0,226, 10, 7, 0,227, 10, 7, 0,228, 10,188, 1,229, 10,188, 1,230, 10,188, 1,231, 10, 54, 0, 11, 0, + 4, 0, 18, 0, 4, 0, 63, 0, 4, 0,232, 10, 4, 0,233, 10, 19, 0,234, 10, 19, 0,235, 10,189, 1,236, 10, 7, 0,237, 10, + 7, 0,238, 10, 7, 0,239, 10, 7, 0,240, 10, 0, 1, 10, 0, 4, 0,254, 9, 4, 0,241, 10, 7, 0,242, 10, 7, 0,243, 10, + 7, 0,244, 10, 7, 0,245, 10, 7, 0, 9, 0, 7, 0, 11, 0, 4, 0, 87, 1, 4, 0, 1, 3,255, 0, 18, 0, 4, 0,132, 0, + 4, 0,246, 10, 4, 0,247, 10, 7, 0,248, 10, 4, 0,249, 10, 7, 0,250, 10, 7, 0,251, 10, 4, 0,252, 10, 7, 0,253, 10, + 4, 0,254, 10, 7, 0,255, 10, 0, 1, 0, 11, 7, 0, 1, 11, 7, 0, 2, 11, 7, 0, 3, 11, 7, 0, 4, 11, 4, 0, 5, 11, + 4, 0, 27, 0,190, 1, 4, 0, 42, 0,244, 2, 7, 0, 6, 11, 7, 0,178, 1, 7, 0, 27, 0,213, 0, 34, 0, 22, 0, 32, 0, +190, 1, 7, 11, 54, 0,229, 10, 46, 0, 8, 11, 52, 0, 9, 11, 25, 0,154, 0, 0, 0, 10, 11, 7, 0, 11, 11, 2, 0,109, 6, + 2, 0, 12, 11, 4, 0,108, 0, 4, 0, 18, 0, 7, 0, 13, 11, 4, 0, 90, 2, 4, 0, 14, 11, 7, 0, 15, 11, 7, 0, 16, 11, + 7, 0, 17, 11, 7, 0,178, 1, 4, 0, 18, 11, 7, 0, 19, 11, 0, 0, 20, 11, 0, 0, 21, 11, 0, 0, 22, 11, 0, 0, 23, 11, + 7, 0, 24, 11, 7, 0, 25, 11, 7, 0, 26, 11, 7, 0, 1, 3, 7, 0, 27, 11, 4, 0, 28, 11, 7, 0,240, 5, 7, 0, 29, 11, + 7, 0, 30, 11,191, 1, 10, 0, 4, 0, 16, 0, 4, 0,128, 0, 4, 0, 18, 0, 4, 0, 15, 4, 4, 0, 31, 11, 4, 0, 32, 11, + 4, 0, 33, 11, 4, 0, 70, 0, 0, 0, 19, 0, 11, 0, 2, 0,192, 1, 1, 0, 0, 0, 70, 7, 95, 0, 8, 0,191, 1, 34, 11, + 4, 0, 35, 11, 4, 0, 36, 11, 4, 0, 37, 11, 4, 0, 38, 11, 4, 0, 30, 0, 11, 0, 39, 11,192, 1, 40, 11,193, 1, 5, 0, + 7, 0,165, 2, 7, 0,240, 2, 7, 0, 40, 2, 2, 0,147, 2, 2, 0, 27, 0,194, 1, 5, 0, 7, 0,165, 2, 7, 0,159, 4, + 7, 0, 41, 11, 7, 0, 42, 11, 7, 0,240, 2,195, 1, 5, 0, 27, 0, 43, 11,196, 1, 21, 0, 7, 0, 75, 6, 7, 0, 44, 11, + 7, 0, 56, 0,197, 1, 3, 0, 7, 0, 45, 11, 4, 0, 46, 11, 4, 0, 47, 11,198, 1, 7, 0, 4, 0, 48, 11, 4, 0, 49, 11, + 4, 0, 50, 11, 7, 0, 51, 11, 7, 0, 52, 11, 7, 0, 53, 11, 7, 0, 56, 0,199, 1, 8, 0,199, 1, 0, 0,199, 1, 1, 0, + 27, 0, 44, 0, 4, 0, 3, 1, 2, 0, 18, 0, 2, 0, 87, 1, 7, 0,240, 2, 7, 0, 56, 9,200, 1, 7, 0,200, 1, 0, 0, +200, 1, 1, 0, 27, 0, 44, 0, 2, 0,225, 2, 2, 0, 18, 0, 2, 0, 14, 2, 2, 0, 56, 0,201, 1, 17, 0,194, 1, 8, 4, +194, 1, 54, 11,193, 1, 55, 11,194, 1, 39, 9,195, 1, 56, 11, 4, 0, 82, 0, 7, 0,240, 2, 7, 0, 7, 3, 7, 0, 57, 11, + 4, 0, 48, 11, 4, 0, 58, 11, 7, 0, 52, 11, 7, 0, 53, 11, 7, 0,108, 0, 4, 0, 59, 11, 2, 0, 18, 0, 2, 0, 60, 11, +202, 1, 15, 0, 7, 0,255, 0, 7, 0, 61, 11, 7, 0, 45, 11, 7, 0, 62, 11, 7, 0, 63, 11, 7, 0, 64, 11, 7, 0, 65, 11, + 7, 0, 66, 11, 7, 0, 67, 11, 7, 0, 68, 11, 7, 0, 69, 11, 7, 0, 70, 11, 7, 0, 71, 11, 4, 0, 18, 0, 4, 0, 72, 11, +203, 1,128, 0, 22, 0, 32, 0, 34, 0, 75, 0,204, 1, 73, 11,202, 1, 74, 11,187, 0,154, 4, 4, 0, 18, 0, 4, 0, 56, 0, + 2, 0, 16, 0, 2, 0, 58, 10, 2, 0, 75, 11, 2, 0,122, 1, 2, 0, 76, 11, 2, 0,232, 3, 2, 0, 77, 11, 2, 0, 78, 11, + 2, 0, 79, 11, 2, 0, 80, 11, 2, 0, 81, 11, 2, 0, 82, 11, 2, 0, 83, 11, 2, 0, 84, 11, 2, 0, 85, 11, 2, 0,224, 5, + 2, 0, 86, 11, 2, 0, 87, 11, 2, 0, 88, 11, 2, 0, 89, 11, 2, 0, 90, 11, 2, 0, 29, 2, 2, 0, 32, 9, 2, 0, 7, 9, + 2, 0, 91, 11, 2, 0, 92, 11, 2, 0, 25, 4, 2, 0, 26, 4, 2, 0, 93, 11, 2, 0, 94, 11, 2, 0, 95, 11, 2, 0, 96, 11, + 7, 0, 97, 11, 7, 0, 98, 11, 7, 0, 99, 11, 7, 0,100, 11, 7, 0,101, 11, 7, 0,102, 11, 7, 0,103, 11, 2, 0,154, 5, + 2, 0,104, 11, 7, 0,105, 11, 7, 0,106, 11, 7, 0,107, 11, 7, 0, 14, 9, 7, 0, 91, 0, 7, 0, 7, 3, 7, 0, 20, 9, + 7, 0,108, 11, 7, 0,109, 11, 7, 0,110, 11, 7, 0,111, 11, 7, 0,112, 11, 7, 0,113, 11, 4, 0, 15, 9, 4, 0, 13, 9, + 4, 0,114, 11, 4, 0,115, 11, 2, 0,116, 11, 2, 0,117, 11, 7, 0, 16, 9, 7, 0, 17, 9, 7, 0, 18, 9, 7, 0,118, 11, + 7, 0,119, 11, 7, 0,120, 11, 7, 0,121, 11, 7, 0,122, 11, 7, 0,123, 11, 7, 0,124, 11, 7, 0,125, 11, 7, 0,126, 11, + 7, 0,222, 3, 7, 0,108, 0, 7, 0,127, 11, 7, 0,128, 11, 7, 0,129, 11, 7, 0,130, 11, 7, 0,214, 0, 7, 0,131, 11, + 4, 0,132, 11, 4, 0,133, 11, 7, 0,134, 11, 7, 0,135, 11, 7, 0,136, 11, 7, 0,137, 11, 7, 0,138, 11, 7, 0,213, 0, + 7, 0,139, 11, 7, 0, 52, 4, 7, 0, 50, 4, 7, 0, 51, 4, 7, 0,140, 11, 7, 0,141, 11, 7, 0,142, 11, 7, 0,143, 11, + 7, 0,144, 11, 7, 0,145, 11, 7, 0,146, 11, 7, 0,147, 11, 7, 0,148, 11, 7, 0,149, 11, 7, 0,150, 11, 7, 0,151, 11, + 7, 0,152, 11, 7, 0,153, 11, 7, 0,154, 11, 7, 0,155, 11, 7, 0,156, 11, 7, 0,157, 11, 4, 0,158, 11, 4, 0,159, 11, + 46, 0,140, 1, 64, 0, 0, 4, 14, 0,160, 11, 64, 0,161, 11, 27, 0,162, 11, 27, 0,163, 11, 31, 0, 80, 0,182, 0, 73, 1, +182, 0,164, 11,150, 0, 52, 0,150, 0, 0, 0,150, 0, 1, 0,203, 1,165, 11,201, 1,166, 11,198, 1,217, 9,190, 0, 80, 4, + 11, 0, 81, 4,205, 1,167, 11,205, 1,168, 11, 14, 0,169, 11, 14, 0,170, 11,135, 0,171, 11,143, 0,172, 11,143, 0,173, 11, + 27, 0,174, 11, 27, 0,175, 11, 27, 0, 38, 0, 14, 0, 25, 10, 0, 0, 19, 0, 7, 0,244, 0, 7, 0, 36, 3, 7, 0,176, 11, + 7, 0,177, 11, 4, 0,214, 2, 4, 0,178, 11, 4, 0, 18, 0, 4, 0, 15, 9, 4, 0,179, 11, 4, 0,180, 11, 4, 0,181, 11, + 4, 0,182, 11, 2, 0,251, 0, 2, 0,183, 11, 2, 0,184, 11, 2, 0,185, 11, 0, 0,186, 11, 2, 0,187, 11, 2, 0,188, 11, + 2, 0,189, 11, 11, 0,190, 11,139, 0,153, 4, 14, 0, 21, 3, 14, 0,191, 11,197, 1,192, 11, 4, 0,193, 11, 4, 0,194, 11, +206, 1,195, 11,141, 0, 33, 3,207, 1,196, 11, 7, 0,197, 11, 7, 0,198, 11, 7, 0,199, 11,137, 0, 38, 0,208, 1,151, 9, + 7, 0,123, 4, 7, 0,200, 11, 7, 0,201, 11, 7, 0, 75, 6, 7, 0,236, 3, 7, 0,222, 3, 7, 0,202, 11, 7, 0, 92, 2, + 7, 0,203, 11, 7, 0,204, 11, 7, 0,205, 11, 7, 0,206, 11, 7, 0,207, 11, 7, 0,208, 11, 7, 0,124, 4, 7, 0,209, 11, + 7, 0,210, 11, 7, 0,211, 11, 7, 0,125, 4, 7, 0,121, 4, 7, 0,122, 4, 7, 0,212, 11, 7, 0,213, 11, 7, 0,214, 11, + 4, 0,215, 11, 4, 0, 92, 0, 4, 0,216, 11, 4, 0,217, 11, 2, 0,218, 11, 2, 0,219, 11, 2, 0,220, 11, 2, 0,221, 11, + 2, 0,222, 11, 2, 0,223, 11, 2, 0,224, 11, 2, 0, 27, 0,187, 0,154, 4,138, 0, 11, 0,208, 1,225, 11, 7, 0,226, 11, + 7, 0,227, 11, 7, 0,251, 1, 7, 0,228, 11, 7, 0,229, 11, 7, 0,230, 11, 4, 0, 92, 0, 2, 0,231, 11, 2, 0,232, 11, + 64, 0,250, 1,209, 1, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 7, 0,233, 11,210, 1, 6, 0,210, 1, 0, 0, +210, 1, 1, 0,209, 1,193, 9, 4, 0, 1, 1, 2, 0,234, 11, 2, 0, 18, 0,211, 1, 5, 0,211, 1, 0, 0,211, 1, 1, 0, + 14, 0,235, 11, 4, 0,236, 11, 4, 0, 18, 0,212, 1, 9, 0,212, 1, 0, 0,212, 1, 1, 0, 14, 0,127, 0,211, 1,237, 11, + 4, 0, 18, 0, 2, 0,234, 11, 2, 0,238, 11, 7, 0, 93, 0, 0, 0,239, 11,178, 0, 6, 0, 22, 0, 32, 0, 14, 0,123, 5, + 4, 0, 18, 0, 2, 0,240, 11, 2, 0,241, 11, 11, 0,242, 11,213, 1, 6, 0, 14, 0,243, 11, 4, 0,244, 11, 4, 0,245, 11, + 4, 0, 18, 0, 4, 0, 27, 0,237, 0,246, 11,214, 1, 19, 0, 22, 0, 32, 0,215, 1,247, 11,215, 1,248, 11, 14, 0,249, 11, + 4, 0,250, 11, 2, 0,251, 11, 2, 0,252, 11, 14, 0,253, 11, 14, 0,254, 11,213, 1,255, 11, 14, 0, 0, 12, 14, 0, 1, 12, + 14, 0, 2, 12, 14, 0, 3, 12,216, 1, 4, 12,216, 1, 5, 12,216, 1, 6, 12, 14, 0, 7, 12,237, 0, 8, 12,215, 1, 32, 0, +215, 1, 0, 0,215, 1, 1, 0, 11, 0, 9, 12, 4, 0,119, 8, 2, 0, 10, 12, 2, 0, 27, 0, 27, 1, 11, 12, 27, 1, 12, 12, + 0, 0, 13, 12, 2, 0, 14, 12, 2, 0, 15, 12, 2, 0,141, 8, 2, 0,142, 8, 2, 0, 16, 12, 2, 0, 17, 12, 2, 0, 15, 4, + 2, 0, 53, 7, 2, 0, 18, 12, 2, 0, 19, 12, 2, 0, 20, 12, 2, 0, 30, 0,217, 1, 21, 12,218, 1, 22, 12,219, 1, 23, 12, + 4, 0, 24, 12, 4, 0, 25, 12, 11, 0, 26, 12, 14, 0,254, 11, 14, 0,161, 8, 14, 0, 27, 12, 14, 0, 28, 12, 14, 0, 29, 12, +220, 1, 17, 0,220, 1, 0, 0,220, 1, 1, 0, 0, 0, 30, 12, 21, 0, 31, 0, 2, 0, 31, 12, 2, 0, 16, 0, 2, 0, 14, 0, + 2, 0, 32, 12, 2, 0, 33, 12, 2, 0, 34, 12, 2, 0, 35, 12, 2, 0, 36, 12, 2, 0, 18, 0, 2, 0, 37, 12, 2, 0, 32, 0, + 2, 0, 27, 0,221, 1, 38, 12,222, 1, 4, 0,222, 1, 0, 0,222, 1, 1, 0,220, 1, 39, 12,220, 1, 40, 12,223, 1, 11, 0, +223, 1, 0, 0,223, 1, 1, 0, 14, 0, 41, 12, 14, 0, 42, 12, 0, 0, 30, 12, 2, 0, 43, 12, 2, 0, 44, 12, 2, 0, 18, 0, + 2, 0, 45, 12, 4, 0, 46, 12, 11, 0, 47, 12,216, 1, 7, 0,216, 1, 0, 0,216, 1, 1, 0, 0, 0, 30, 12, 0, 0, 48, 12, + 14, 0, 59, 8, 4, 0, 49, 12, 4, 0, 18, 0,249, 0, 14, 0,249, 0, 0, 0,249, 0, 1, 0, 0, 0, 30, 12, 21, 0, 31, 0, +224, 1,135, 8, 11, 0, 50, 12, 11, 0, 51, 12,221, 1, 38, 12,213, 1, 52, 12, 14, 0, 53, 12,249, 0, 54, 12, 32, 1,239, 6, + 2, 0, 18, 0, 2, 0, 86, 1,225, 1, 12, 0,225, 1, 0, 0,225, 1, 1, 0, 11, 0, 2, 0, 11, 0, 55, 12, 0, 0, 19, 0, + 2, 0, 16, 0, 2, 0, 18, 0, 7, 0,139, 9, 7, 0,129, 0, 7, 0,132, 4, 7, 0, 89, 9, 7, 0, 81, 10,226, 1, 5, 0, + 7, 0, 56, 12, 4, 0, 57, 12, 4, 0, 58, 12, 4, 0, 87, 1, 4, 0, 18, 0,227, 1, 6, 0, 7, 0, 59, 12, 7, 0, 60, 12, + 7, 0, 61, 12, 7, 0, 62, 12, 4, 0, 16, 0, 4, 0, 18, 0,228, 1, 5, 0, 7, 0,117, 9, 7, 0,118, 9, 7, 0,240, 2, + 2, 0, 43, 2, 2, 0, 44, 2,229, 1, 5, 0,228, 1, 2, 0, 4, 0, 53, 0, 7, 0, 63, 12, 7, 0,117, 9, 7, 0,118, 9, +230, 1, 4, 0, 2, 0, 64, 12, 2, 0, 65, 12, 2, 0, 66, 12, 2, 0, 67, 12,231, 1, 2, 0, 37, 0, 37, 7, 21, 0,157, 9, +232, 1, 3, 0, 19, 0, 68, 12, 4, 0, 18, 0, 4, 0, 27, 0,233, 1, 6, 0, 7, 0,108, 0, 7, 0,209, 2, 7, 0, 69, 12, + 7, 0, 27, 0, 2, 0,250, 0, 2, 0, 70, 12,234, 1, 5, 0, 7, 0, 71, 12, 7, 0,128, 0, 7, 0,194, 9, 7, 0,195, 9, + 4, 0, 18, 0,235, 1, 6, 0, 22, 0, 42, 7, 0, 0, 72, 12, 0, 0, 73, 12, 2, 0, 74, 12, 2, 0, 18, 0, 4, 0, 75, 12, +236, 1, 7, 0,236, 1, 0, 0,236, 1, 1, 0, 0, 0, 19, 0,235, 1, 76, 12, 2, 0, 77, 12, 2, 0, 16, 0, 7, 0, 60, 0, +237, 1, 7, 0, 14, 0, 78, 12, 0, 0, 79, 12, 11, 0, 80, 12, 7, 0, 60, 0, 7, 0,139, 9, 4, 0, 16, 0, 4, 0, 18, 0, +238, 1, 3, 0, 7, 0, 81, 12, 4, 0, 18, 0, 4, 0, 27, 0,239, 1, 15, 0,239, 1, 0, 0,239, 1, 1, 0,106, 1, 12, 10, +237, 1, 61, 0, 14, 0,188, 3, 30, 0, 49, 0,238, 1, 82, 12, 4, 0, 53, 0, 7, 0, 60, 0, 2, 0, 18, 0, 2, 0, 22, 1, + 4, 0, 83, 12, 0, 0, 72, 12, 4, 0, 84, 12, 7, 0, 85, 12,240, 1, 2, 0, 0, 0, 86, 12, 0, 0, 87, 12,241, 1, 4, 0, +241, 1, 0, 0,241, 1, 1, 0,176, 0, 70, 3, 14, 0, 88, 12,242, 1, 25, 0,242, 1, 0, 0,242, 1, 1, 0, 14, 0, 89, 12, +176, 0, 87, 9,241, 1, 90, 12, 14, 0, 91, 12, 14, 0,188, 3, 0, 0, 19, 0, 7, 0,139, 9, 7, 0, 92, 12, 7, 0, 90, 0, + 7, 0, 91, 0, 7, 0, 77, 10, 7, 0, 78, 10, 7, 0,253, 2, 7, 0,148, 3, 7, 0, 89, 9, 7, 0, 81, 10, 2, 0, 93, 12, + 2, 0, 94, 12, 2, 0, 67, 0, 2, 0, 16, 0, 11, 0, 95, 12, 4, 0, 18, 0, 4, 0, 30, 0,243, 1, 6, 0,243, 1, 0, 0, +243, 1, 1, 0, 14, 0, 89, 12, 4, 0, 18, 0, 4, 0, 14, 2, 0, 0, 19, 0,244, 1, 11, 0,244, 1, 0, 0,244, 1, 1, 0, + 22, 0, 42, 7, 0, 0, 96, 12, 4, 0, 75, 12, 2, 0, 97, 12, 2, 0, 27, 0, 0, 0, 72, 12, 4, 0, 83, 12, 2, 0, 18, 0, + 2, 0, 98, 12,245, 1, 10, 0,245, 1, 0, 0,245, 1, 1, 0, 14, 0, 99, 12, 0, 0, 30, 12, 0, 0, 19, 0, 0, 0,100, 12, + 0, 0,101, 12, 2, 0, 18, 0, 2, 0, 98, 12, 4, 0,102, 12,246, 1, 5, 0,246, 1, 0, 0,246, 1, 1, 0, 0, 0, 72, 12, + 4, 0, 83, 12, 7, 0,230, 2, 34, 0, 12, 0,176, 0,179, 3,176, 0,103, 12,241, 1, 90, 12, 14, 0,104, 12,242, 1,105, 12, + 14, 0,106, 12, 14, 0,107, 12, 4, 0, 18, 0, 4, 0,251, 0, 2, 0,108, 12, 2, 0,109, 12, 7, 0,110, 12,247, 1, 2, 0, 22, 0, 32, 0, 34, 0, 75, 0,248, 1, 5, 0,248, 1, 0, 0,248, 1, 1, 0, 4, 0, 16, 0, 4, 0, 18, 0, 0, 0,172, 5, -249, 1, 6, 0,248, 1,110, 12, 27, 0, 44, 0, 4, 0,111, 12, 7, 0,112, 12, 4, 0,113, 12, 4, 0,253, 9,250, 1, 3, 0, -248, 1,110, 12, 4, 0,111, 12, 7, 0,114, 12,251, 1, 8, 0,248, 1,110, 12, 27, 0, 44, 0, 7, 0, 77, 1, 7, 0,115, 12, - 7, 0, 36, 3, 7, 0,149, 9, 4, 0,111, 12, 4, 0,116, 12,252, 1, 5, 0,248, 1,110, 12, 7, 0,117, 12, 7, 0,176, 2, - 7, 0, 3, 3, 7, 0, 56, 0,253, 1, 3, 0,248, 1,110, 12, 7, 0,149, 9, 7, 0,118, 12,196, 1, 4, 0, 7, 0,119, 12, - 7, 0,127, 11, 2, 0,120, 12, 2, 0, 87, 1,254, 1, 14, 0,254, 1, 0, 0,254, 1, 1, 0, 14, 0,121, 12, 14, 0,122, 12, - 14, 0,123, 12, 0, 0,172, 5, 4, 0, 32, 0, 4, 0, 18, 0, 4, 0,124, 12, 7, 0,125, 12, 4, 0,113, 12, 4, 0,253, 9, - 7, 0, 84, 4, 7, 0, 5, 3,204, 1, 23, 0, 4, 0,111, 12, 4, 0,126, 12, 7, 0,127, 12, 7, 0, 1, 3, 7, 0,128, 12, - 7, 0,229, 8, 7, 0,119, 12, 7, 0,129, 12, 7, 0,209, 2, 7, 0,247, 10, 7, 0,217, 4, 7, 0,130, 12, 7, 0,131, 12, - 7, 0,132, 12, 7, 0,133, 12, 7, 0,134, 12, 7, 0,135, 12, 7, 0,136, 12, 7, 0,137, 12, 7, 0,138, 12, 7, 0,139, 12, - 7, 0,140, 12, 14, 0,141, 12,123, 0, 40, 0,122, 0,142, 12,255, 1, 73, 11, 64, 0,143, 12, 64, 0,160, 11, 64, 0,144, 12, - 0, 2,145, 12, 43, 0,169, 0, 43, 0,146, 12, 43, 0,147, 12, 7, 0,148, 12, 7, 0,149, 12, 7, 0,150, 12, 7, 0,151, 12, - 7, 0,152, 12, 7, 0,118, 8, 7, 0,153, 12, 7, 0,178, 1, 7, 0,154, 12, 4, 0,155, 12, 4, 0,156, 12, 4, 0,157, 12, - 4, 0, 92, 0, 4, 0, 27, 0, 4, 0,158, 12, 2, 0,159, 12, 2, 0,160, 12, 4, 0,161, 12, 7, 0,209, 2, 4, 0,162, 12, - 7, 0,163, 12, 4, 0,164, 12, 4, 0,165, 12, 4, 0,166, 12,139, 0,167, 12, 14, 0,168, 12,187, 0,154, 4, 4, 0,169, 12, - 7, 0,170, 12, 7, 0,171, 12, 4, 0, 30, 0,124, 0, 12, 0,122, 0,142, 12,150, 0, 56, 3, 7, 0,143, 1, 7, 0,118, 8, - 7, 0,172, 12, 7, 0,173, 12, 7, 0,174, 12, 2, 0,175, 12, 2, 0,176, 12, 2, 0,177, 12, 2, 0, 16, 0, 4, 0, 92, 0, -125, 0, 13, 0,122, 0,142, 12,141, 0, 33, 3,143, 0, 35, 3, 7, 0,192, 9, 7, 0,178, 12, 7, 0,179, 12, 7, 0, 79, 1, - 7, 0,180, 12, 4, 0, 33, 10, 4, 0, 29, 3, 2, 0, 16, 0, 2, 0, 27, 0, 4, 0, 30, 0, 1, 2, 15, 0, 22, 0, 32, 0, - 34, 0, 75, 0, 46, 1,227, 8, 7, 0,181, 12, 7, 0,182, 12, 7, 0,183, 12, 7, 0,184, 12, 7, 0,148, 9, 7, 0,185, 12, - 7, 0,186, 12, 7, 0,187, 12, 7, 0, 84, 4, 7, 0,229, 8, 2, 0, 18, 0, 2, 0,112, 9,231, 0, 3, 0, 4, 0,126, 0, - 2, 0,215, 6, 2, 0,188, 12, 2, 2, 5, 0, 0, 0,193, 8, 2, 0,194, 8, 2, 0, 72, 5, 2, 0,189, 12, 2, 0,190, 12, -229, 0, 16, 0, 22, 0, 32, 0, 34, 0, 75, 0, 0, 0, 35, 0, 4, 0,143, 0, 4, 0,144, 0, 4, 0,191, 12, 7, 0,162, 0, - 7, 0,163, 0, 44, 0,138, 0, 3, 2,150, 9,178, 0,182, 3, 4, 2,192, 12, 11, 0,193, 12, 2, 2,194, 12, 4, 0, 18, 0, - 4, 0, 22, 0, 13, 1, 10, 0, 4, 0,132, 0, 4, 0,195, 12, 52, 0,196, 12, 7, 0,197, 12, 2, 0,198, 12, 0, 0,181, 2, - 4, 0,126, 0, 5, 2,175, 3, 6, 2,199, 12, 7, 0,200, 12, 7, 2, 3, 0, 4, 0,126, 0, 7, 0,201, 12, 7, 0, 79, 1, - 8, 2, 11, 0, 11, 0,202, 12, 7, 0,203, 12, 7, 0,204, 12, 7, 0, 27, 0, 7, 0,205, 12, 2, 0,206, 12, 2, 0, 91, 0, - 7, 0,207, 12, 7, 0,208, 12, 7, 0,209, 12, 7, 0,210, 12, 6, 2, 3, 0, 7, 0,211, 12, 4, 0,126, 0, 4, 0, 18, 0, - 5, 2, 24, 0, 5, 2, 0, 0, 5, 2, 1, 0, 0, 0, 19, 0, 7, 0,212, 12, 7, 0,213, 12, 7, 0,214, 12, 7, 0,215, 12, - 7, 0, 5, 11, 4, 0,216, 12, 4, 0,217, 12, 6, 2,218, 12, 7, 0,219, 12, 7, 0,201, 12, 4, 0, 18, 0, 4, 0,220, 12, - 4, 0,221, 12, 7, 0, 84, 12, 2, 0,222, 12, 2, 0,227, 3, 2, 0,223, 12, 2, 0,224, 12, 2, 0,225, 12, 2, 0, 30, 0, - 7, 0,226, 12, 9, 2, 22, 0, 4, 0, 18, 0, 2, 0,227, 12, 2, 0,228, 12, 7, 0,229, 12, 2, 0,230, 12, 2, 0,231, 12, - 2, 0,232, 12, 2, 0,233, 12, 2, 0,234, 12, 2, 0,235, 12, 2, 0,236, 12, 2, 0, 3, 3, 4, 0,237, 12, 4, 0,238, 12, - 2, 0,239, 12, 2, 0,240, 12, 7, 0, 94, 1, 4, 0,241, 12, 4, 0,242, 12, 7, 0,243, 12, 7, 0,244, 12, 4, 0, 74, 0, +249, 1, 6, 0,248, 1,111, 12, 27, 0, 44, 0, 4, 0,112, 12, 7, 0,113, 12, 4, 0,114, 12, 4, 0,254, 9,250, 1, 3, 0, +248, 1,111, 12, 4, 0,112, 12, 7, 0,115, 12,251, 1, 8, 0,248, 1,111, 12, 27, 0, 44, 0, 7, 0, 77, 1, 7, 0,116, 12, + 7, 0, 36, 3, 7, 0,150, 9, 4, 0,112, 12, 4, 0,117, 12,252, 1, 5, 0,248, 1,111, 12, 7, 0,118, 12, 7, 0,176, 2, + 7, 0, 3, 3, 7, 0, 56, 0,253, 1, 3, 0,248, 1,111, 12, 7, 0,150, 9, 7, 0,119, 12,196, 1, 4, 0, 7, 0,120, 12, + 7, 0,128, 11, 2, 0,121, 12, 2, 0, 87, 1,254, 1, 14, 0,254, 1, 0, 0,254, 1, 1, 0, 14, 0,122, 12, 14, 0,123, 12, + 14, 0,124, 12, 0, 0,172, 5, 4, 0, 32, 0, 4, 0, 18, 0, 4, 0,125, 12, 7, 0,126, 12, 4, 0,114, 12, 4, 0,254, 9, + 7, 0, 84, 4, 7, 0, 5, 3,204, 1, 23, 0, 4, 0,112, 12, 4, 0,127, 12, 7, 0,128, 12, 7, 0, 1, 3, 7, 0,129, 12, + 7, 0,230, 8, 7, 0,120, 12, 7, 0,130, 12, 7, 0,209, 2, 7, 0,248, 10, 7, 0,217, 4, 7, 0,131, 12, 7, 0,132, 12, + 7, 0,133, 12, 7, 0,134, 12, 7, 0,135, 12, 7, 0,136, 12, 7, 0,137, 12, 7, 0,138, 12, 7, 0,139, 12, 7, 0,140, 12, + 7, 0,141, 12, 14, 0,142, 12,123, 0, 40, 0,122, 0,143, 12,255, 1, 74, 11, 64, 0,144, 12, 64, 0,161, 11, 64, 0,145, 12, + 0, 2,146, 12, 43, 0,169, 0, 43, 0,147, 12, 43, 0,148, 12, 7, 0,149, 12, 7, 0,150, 12, 7, 0,151, 12, 7, 0,152, 12, + 7, 0,153, 12, 7, 0,118, 8, 7, 0,154, 12, 7, 0,178, 1, 7, 0,155, 12, 4, 0,156, 12, 4, 0,157, 12, 4, 0,158, 12, + 4, 0, 92, 0, 4, 0, 27, 0, 4, 0,159, 12, 2, 0,160, 12, 2, 0,161, 12, 4, 0,162, 12, 7, 0,209, 2, 4, 0,163, 12, + 7, 0,164, 12, 4, 0,165, 12, 4, 0,166, 12, 4, 0,167, 12,139, 0,168, 12, 14, 0,169, 12,187, 0,154, 4, 4, 0,170, 12, + 7, 0,171, 12, 7, 0,172, 12, 4, 0, 30, 0,124, 0, 12, 0,122, 0,143, 12,150, 0, 56, 3, 7, 0,143, 1, 7, 0,118, 8, + 7, 0,173, 12, 7, 0,174, 12, 7, 0,175, 12, 2, 0,176, 12, 2, 0,177, 12, 2, 0,178, 12, 2, 0, 16, 0, 4, 0, 92, 0, +125, 0, 13, 0,122, 0,143, 12,141, 0, 33, 3,143, 0, 35, 3, 7, 0,193, 9, 7, 0,179, 12, 7, 0,180, 12, 7, 0, 79, 1, + 7, 0,181, 12, 4, 0, 34, 10, 4, 0, 29, 3, 2, 0, 16, 0, 2, 0, 27, 0, 4, 0, 30, 0, 1, 2, 15, 0, 22, 0, 32, 0, + 34, 0, 75, 0, 46, 1,228, 8, 7, 0,182, 12, 7, 0,183, 12, 7, 0,184, 12, 7, 0,185, 12, 7, 0,149, 9, 7, 0,186, 12, + 7, 0,187, 12, 7, 0,188, 12, 7, 0, 84, 4, 7, 0,230, 8, 2, 0, 18, 0, 2, 0,113, 9,231, 0, 3, 0, 4, 0,126, 0, + 2, 0,215, 6, 2, 0,189, 12, 2, 2, 5, 0, 0, 0,194, 8, 2, 0,195, 8, 2, 0, 72, 5, 2, 0,190, 12, 2, 0,191, 12, +229, 0, 16, 0, 22, 0, 32, 0, 34, 0, 75, 0, 0, 0, 35, 0, 4, 0,143, 0, 4, 0,144, 0, 4, 0,192, 12, 7, 0,162, 0, + 7, 0,163, 0, 44, 0,138, 0, 3, 2,151, 9,178, 0,182, 3, 4, 2,193, 12, 11, 0,194, 12, 2, 2,195, 12, 4, 0, 18, 0, + 4, 0, 22, 0, 13, 1, 10, 0, 4, 0,132, 0, 4, 0,196, 12, 52, 0,197, 12, 7, 0,198, 12, 2, 0,199, 12, 0, 0,181, 2, + 4, 0,126, 0, 5, 2,175, 3, 6, 2,200, 12, 7, 0,201, 12, 7, 2, 3, 0, 4, 0,126, 0, 7, 0,202, 12, 7, 0, 79, 1, + 8, 2, 11, 0, 11, 0,203, 12, 7, 0,204, 12, 7, 0,205, 12, 7, 0, 27, 0, 7, 0,206, 12, 2, 0,207, 12, 2, 0, 67, 0, + 7, 0,208, 12, 7, 0,209, 12, 7, 0,210, 12, 7, 0,211, 12, 6, 2, 3, 0, 7, 0,212, 12, 4, 0,126, 0, 4, 0, 18, 0, + 5, 2, 24, 0, 5, 2, 0, 0, 5, 2, 1, 0, 0, 0, 19, 0, 7, 0,213, 12, 7, 0,214, 12, 7, 0,215, 12, 7, 0,216, 12, + 7, 0, 6, 11, 4, 0,217, 12, 4, 0,218, 12, 6, 2,219, 12, 7, 0,220, 12, 7, 0,202, 12, 4, 0, 18, 0, 4, 0,221, 12, + 4, 0,222, 12, 7, 0, 85, 12, 2, 0,223, 12, 2, 0,227, 3, 2, 0,224, 12, 2, 0,225, 12, 2, 0,226, 12, 2, 0, 30, 0, + 7, 0,227, 12, 9, 2, 22, 0, 4, 0, 18, 0, 2, 0,228, 12, 2, 0,229, 12, 7, 0,230, 12, 2, 0,231, 12, 2, 0,232, 12, + 2, 0,233, 12, 2, 0,234, 12, 2, 0,235, 12, 2, 0,236, 12, 2, 0,237, 12, 2, 0, 3, 3, 4, 0,238, 12, 4, 0,239, 12, + 2, 0,240, 12, 2, 0, 30, 0, 7, 0, 94, 1, 4, 0,241, 12, 4, 0,242, 12, 7, 0,243, 12, 7, 0,244, 12, 4, 0,247, 1, 10, 2, 12, 0, 4, 0, 18, 0, 4, 0,245, 12, 4, 0,246, 12, 7, 0,247, 12, 5, 2,248, 12, 7, 0,249, 12, 7, 0,250, 12, - 7, 0,251, 12, 4, 0,190, 1, 4, 0,132, 0, 7, 0,148, 3, 52, 0,252, 12, 11, 2, 5, 0, 4, 0, 18, 0, 7, 0,201, 12, + 7, 0,251, 12, 4, 0,190, 1, 4, 0,132, 0, 7, 0,148, 3, 52, 0,252, 12, 11, 2, 5, 0, 4, 0, 18, 0, 7, 0,202, 12, 4, 0,253, 12, 4, 0,254, 12, 7, 2,255, 12, 12, 2, 7, 0, 12, 2, 0, 0, 12, 2, 1, 0, 0, 0, 19, 0, 4, 0, 18, 0, 7, 0,148, 3, 14, 0, 0, 13, 11, 2, 1, 13, 13, 2, 1, 0, 0, 0, 2, 13, 4, 2, 10, 0, 9, 2, 3, 13, 8, 2, 4, 13, 14, 0, 0, 13, 11, 2, 1, 13, 10, 2, 5, 13, 5, 2, 6, 13, 14, 0, 7, 13, 4, 0, 8, 13, 4, 0, 9, 13, 13, 2, 90, 6, 14, 2, 48, 0, 14, 2, 0, 0, 14, 2, 1, 0,169, 0,145, 3, 15, 2, 2, 0, 64, 0, 10, 13,187, 0,154, 4,139, 0,153, 4, - 14, 0, 21, 3, 4, 0, 11, 13, 0, 0, 19, 0, 2, 0,162, 10, 2, 0, 16, 0, 2, 0, 12, 13, 2, 0, 13, 13, 2, 0, 14, 13, - 2, 0, 15, 13, 2, 0, 16, 13, 2, 0, 17, 13, 4, 0, 92, 0, 4, 0,186, 3, 4, 0, 18, 13, 4, 0, 19, 13, 4, 0,193, 9, - 4, 0,194, 9, 4, 0, 27, 0, 7, 0, 20, 13, 47, 0, 21, 13, 0, 0, 22, 13, 4, 0, 23, 13, 4, 0,161, 12, 7, 0, 24, 13, + 14, 0, 21, 3, 4, 0, 11, 13, 0, 0, 19, 0, 2, 0,163, 10, 2, 0, 16, 0, 2, 0, 12, 13, 2, 0, 13, 13, 2, 0, 14, 13, + 2, 0, 15, 13, 2, 0, 16, 13, 2, 0, 17, 13, 4, 0, 92, 0, 4, 0,186, 3, 4, 0, 18, 13, 4, 0, 19, 13, 4, 0,194, 9, + 4, 0,195, 9, 4, 0, 27, 0, 7, 0, 20, 13, 47, 0, 21, 13, 0, 0, 22, 13, 4, 0, 23, 13, 4, 0,162, 12, 7, 0, 24, 13, 7, 0, 25, 13, 7, 0, 26, 13, 7, 0, 27, 13, 7, 0, 28, 13, 7, 0, 29, 13, 7, 0, 30, 13, 7, 0, 31, 13, 7, 0, 32, 13, 7, 0, 33, 13, 7, 0, 34, 13, 7, 0, 35, 13, 7, 0, 36, 13, 7, 0, 37, 13, 0, 0,202, 2, 0, 0, 38, 13, 0, 0, 39, 13, 0, 0, 40, 13,169, 0, 7, 0,168, 0, 41, 13,143, 0, 35, 3, 14, 0, 42, 13, 2, 0, 43, 13, 2, 0, 92, 0, 4, 0, 27, 0, - 0, 0, 44, 13,170, 0, 24, 0,168, 0, 41, 13,143, 0, 35, 3,150, 0, 56, 3, 63, 0, 25, 2, 4, 0, 92, 0, 4, 0, 45, 13, + 0, 0, 44, 13,170, 0, 24, 0,168, 0, 41, 13,143, 0, 35, 3,150, 0, 56, 3, 63, 0, 26, 2, 4, 0, 92, 0, 4, 0, 45, 13, 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0, 7, 0,178, 1, 7, 0, 46, 13, 7, 0, 47, 13, 7, 0, 48, 13, 7, 0, 49, 13, - 50, 0, 50, 13, 50, 0, 51, 13, 2, 0, 52, 13, 2, 0,222, 10, 2, 0, 53, 13, 2, 0, 27, 0, 7, 0, 54, 13, 7, 0, 55, 13, + 50, 0, 50, 13, 50, 0, 51, 13, 2, 0, 52, 13, 2, 0,223, 10, 2, 0, 53, 13, 2, 0, 27, 0, 7, 0, 54, 13, 7, 0, 55, 13, 7, 0, 56, 13, 7, 0, 57, 13, 69, 78, 68, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 4474ea7f281..dd306d38765 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -33,6 +33,7 @@ struct ARegion; struct bContext; +struct bScreen; struct ImBuf; struct Main; struct MovieClip; @@ -42,7 +43,7 @@ struct wmEvent; /* clip_editor.c */ int ED_space_clip_poll(struct bContext *C); -void ED_space_clip_set(struct bContext *C, struct SpaceClip *sc, struct MovieClip *clip); +void ED_space_clip_set(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip); struct MovieClip *ED_space_clip(struct SpaceClip *sc); void ED_space_clip_size(struct SpaceClip *sc, int *width, int *height); void ED_space_clip_zoom(struct SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 9f4a351c66d..5e754fe3619 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -864,6 +864,9 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->tclip.cframe, 0x60, 0xc0, 0x40, 255); rgba_char_args_set(btheme->tclip.handle_vertex, 0x00, 0x00, 0x00, 0xff); rgba_char_args_set(btheme->tclip.handle_vertex_select, 0xff, 0xff, 0, 0xff); + rgba_char_args_set(btheme->tclip.list, 0x66, 0x66, 0x66, 0xff); + rgba_char_args_set(btheme->tclip.strip, 0x0c, 0x0a, 0x0a, 0x80); + rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff); btheme->tclip.handle_vertex_size = 4; } @@ -1776,6 +1779,17 @@ void init_userdef_do_versions(void) } } + if (bmain->versionfile < 262 || (bmain->versionfile == 262 && bmain->subversionfile < 5)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + if (btheme->tclip.strip[0] == 0) { + rgba_char_args_set(btheme->tclip.list, 0x66, 0x66, 0x66, 0xff); + rgba_char_args_set(btheme->tclip.strip, 0x0c, 0x0a, 0x0a, 0x80); + rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff); + } + } + } + /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { U.texcollectrate = 60; diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt index 30d2fe57c10..ec5e81e4b2c 100644 --- a/source/blender/editors/space_clip/CMakeLists.txt +++ b/source/blender/editors/space_clip/CMakeLists.txt @@ -40,15 +40,17 @@ set(INC_SYS ) set(SRC - space_clip.c - clip_draw.c - clip_toolbar.c - clip_ops.c - clip_graph_ops.c - clip_graph_draw.c - clip_editor.c clip_buttons.c + clip_dopesheet_draw.c + clip_dopesheet_ops.c + clip_draw.c + clip_editor.c + clip_graph_draw.c + clip_graph_ops.c + clip_ops.c + clip_toolbar.c clip_utils.c + space_clip.c tracking_ops.c clip_intern.h diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index eabd64bdc4f..df6d713d82d 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -63,6 +63,13 @@ /* Panels */ +static int clip_grease_pencil_panel_poll(const bContext *C, PanelType *UNUSED(pt)) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + return sc->view == SC_VIEW_CLIP; +} + void ED_clip_buttons_register(ARegionType *art) { PanelType *pt; @@ -72,6 +79,7 @@ void ED_clip_buttons_register(ARegionType *art) strcpy(pt->label, "Grease Pencil"); pt->draw = gpencil_panel_standard; pt->flag |= PNL_DEFAULT_CLOSED; + pt->poll = clip_grease_pencil_panel_poll; BLI_addtail(&art->paneltypes, pt); } diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c new file mode 100644 index 00000000000..3da5ec10582 --- /dev/null +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -0,0 +1,380 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_clip/clip_graph_draw.c + * \ingroup spclip + */ + +#include "DNA_movieclip_types.h" +#include "DNA_object_types.h" /* SELECT */ +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_context.h" +#include "BKE_movieclip.h" +#include "BKE_tracking.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "ED_screen.h" +#include "ED_clip.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "WM_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "BLF_api.h" + +#include "RNA_access.h" + +#include "clip_intern.h" // own include + +static void track_channel_color(MovieTrackingTrack *track, float default_color[3], float color[3]) +{ + if (track->flag & TRACK_CUSTOMCOLOR) { + float bg[3]; + UI_GetThemeColor3fv(TH_HEADER, bg); + + interp_v3_v3v3(color, track->color, bg, 0.5); + } + else { + if (default_color) + copy_v3_v3(color, default_color); + else + UI_GetThemeColor3fv(TH_HEADER, color); + } +} + +static void draw_keyframe_shape(float x, float y, float xscale, float yscale, short sel, float alpha) +{ + /* coordinates for diamond shape */ + static const float _unit_diamond_shape[4][2] = { + {0.0f, 1.0f}, /* top vert */ + {1.0f, 0.0f}, /* mid-right */ + {0.0f, -1.0f}, /* bottom vert */ + {-1.0f, 0.0f} /* mid-left */ + }; + static GLuint displist1 = 0; + static GLuint displist2 = 0; + int hsize = STRIP_HEIGHT_HALF; + + /* initialize 2 display lists for diamond shape - one empty, one filled */ + if (displist1 == 0) { + displist1 = glGenLists(1); + glNewList(displist1, GL_COMPILE); + + glBegin(GL_LINE_LOOP); + glVertex2fv(_unit_diamond_shape[0]); + glVertex2fv(_unit_diamond_shape[1]); + glVertex2fv(_unit_diamond_shape[2]); + glVertex2fv(_unit_diamond_shape[3]); + glEnd(); + glEndList(); + } + if (displist2 == 0) { + displist2 = glGenLists(1); + glNewList(displist2, GL_COMPILE); + + glBegin(GL_QUADS); + glVertex2fv(_unit_diamond_shape[0]); + glVertex2fv(_unit_diamond_shape[1]); + glVertex2fv(_unit_diamond_shape[2]); + glVertex2fv(_unit_diamond_shape[3]); + glEnd(); + glEndList(); + } + + glPushMatrix(); + + /* adjust view transform before starting */ + glTranslatef(x, y, 0.0f); + glScalef(1.0f/xscale*hsize, 1.0f/yscale*hsize, 1.0f); + + /* anti-aliased lines for more consistent appearance */ + glEnable(GL_LINE_SMOOTH); + + if (sel) + UI_ThemeColorShadeAlpha(TH_STRIP_SELECT, 50, -255*(1.0f-alpha)); + else + glColor4f(0.91f, 0.91f, 0.91f, alpha); + + glCallList(displist2); + + /* exterior - black frame */ + glColor4f(0.0f, 0.0f, 0.0f, alpha); + glCallList(displist1); + + glDisable(GL_LINE_SMOOTH); + + /* restore view transform */ + glPopMatrix(); +} + +void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) +{ + MovieClip *clip = ED_space_clip(sc); + View2D *v2d = &ar->v2d; + + /* frame range */ + clip_draw_sfra_efra(v2d, scene); + + if (clip) { + MovieTracking *tracking = &clip->tracking; + MovieTrackingTrack *track; + ListBase *tracksbase = BKE_tracking_get_tracks(tracking); + float y, xscale, yscale; + float strip[4], selected_strip[4]; + + y = (float) CHANNEL_FIRST; + + UI_view2d_getscale(v2d, &xscale, &yscale); + + /* setup colors for regular and selected strips */ + UI_GetThemeColor3fv(TH_STRIP, strip); + UI_GetThemeColor3fv(TH_STRIP_SELECT, selected_strip); + + strip[3] = 0.5f; + selected_strip[3] = 1.0f; + + glEnable(GL_BLEND); + + for (track = tracksbase->first; track; track = track->next) { + float yminc = (float) (y - CHANNEL_HEIGHT_HALF); + float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); + + if (!TRACK_VIEW_SELECTED(sc, track)) + continue; + + /* check if visible */ + if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) + { + float alpha; + int i, sel = track->flag & TRACK_DOPE_SEL; + + /* selection background */ + if (sel) { + float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; + float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f}; + + track_channel_color(track, default_color, color); + glColor4fv(color); + + glRectf(v2d->cur.xmin, (float)y - CHANNEL_HEIGHT_HALF, + v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); + } + + alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f; + + /* tracked segments */ + i = 0; + while (i < track->markersnr) { + MovieTrackingMarker *marker = &track->markers[i]; + + if ((marker->flag & MARKER_DISABLED) == 0) { + MovieTrackingMarker *start_marker = marker; + int prev_fra = marker->framenr, len = 0; + + i++; + while (i < track->markersnr) { + marker = &track->markers[i]; + + if (marker->framenr != prev_fra + 1) + break; + if (marker->flag & MARKER_DISABLED) + break; + + prev_fra = marker->framenr; + len++; + i++; + } + + if (sel) + glColor4fv(selected_strip); + else + glColor4fv(strip); + + glRectf(start_marker->framenr, (float)y - STRIP_HEIGHT_HALF, + start_marker->framenr + len, (float) y + STRIP_HEIGHT_HALF); + + draw_keyframe_shape(start_marker->framenr, y, xscale, yscale, sel, alpha); + draw_keyframe_shape(start_marker->framenr + len, y, xscale, yscale, sel, alpha); + } + + i++; + } + + /* keyframes */ + i = 0; + while (i < track->markersnr) { + MovieTrackingMarker *marker = &track->markers[i]; + + if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) + draw_keyframe_shape(marker->framenr, y, xscale, yscale, sel, alpha); + + i++; + } + } + + /* adjust y-position for next one */ + y -= CHANNEL_STEP; + } + + glDisable(GL_BLEND); + } + + /* current frame */ + clip_draw_cfra(sc, ar, scene); +} + +void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) +{ + ScrArea *sa = CTX_wm_area(C); + SpaceClip *sc = CTX_wm_space_clip(C); + View2D *v2d = &ar->v2d; + MovieClip *clip = ED_space_clip(sc); + MovieTracking *tracking; + MovieTrackingTrack *track; + ListBase *tracksbase; + uiStyle *style = UI_GetStyle(); + uiBlock *block; + int fontid = style->widget.uifont_id; + int items, height; + float y; + + if (!clip) + return; + + tracking = &clip->tracking; + tracksbase = BKE_tracking_get_tracks(tracking); + items = BLI_countlist(tracksbase); + height = (items * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2); + + if (height > (v2d->mask.ymax - v2d->mask.ymin)) { + /* don't use totrect set, as the width stays the same + * (NOTE: this is ok here, the configuration is pretty straightforward) + */ + v2d->tot.ymin = (float)(-height); + } + + /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */ + UI_view2d_sync(NULL, sa, v2d, V2D_LOCK_COPY); + + /* loop through channels, and set up drawing depending on their type + * first pass: just the standard GL-drawing for backdrop + text + */ + y = (float) CHANNEL_FIRST; + + BLF_size(fontid, 11.0f, U.dpi); + + for (track = tracksbase->first; track; track = track->next) { + float yminc = (float) (y - CHANNEL_HEIGHT_HALF); + float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); + + if (!TRACK_VIEW_SELECTED(sc, track)) + continue; + + /* check if visible */ + if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) + { + float font_height, color[3]; + int sel = track->flag & TRACK_DOPE_SEL; + + track_channel_color(track, NULL, color); + glColor3fv(color); + + glRectf(v2d->cur.xmin, (float)y - CHANNEL_HEIGHT_HALF, + v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); + + if (sel) + UI_ThemeColor(TH_TEXT_HI); + else + UI_ThemeColor(TH_TEXT); + + font_height = BLF_height(fontid, track->name); + BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD, + y - font_height / 2.0f, 0.0f); + BLF_draw(fontid, track->name, strlen(track->name)); + } + + /* adjust y-position for next one */ + y -= CHANNEL_STEP; + } + + /* second pass: widgets */ + block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); + y = (float) CHANNEL_FIRST; + + glEnable(GL_BLEND); + for (track = tracksbase->first; track; track = track->next) { + float yminc = (float)(y - CHANNEL_HEIGHT_HALF); + float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF); + + if (!TRACK_VIEW_SELECTED(sc, track)) + continue; + + /* check if visible */ + if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) + { + uiBut *but; + PointerRNA ptr; + int icon; + + RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr); + + if (track->flag & TRACK_LOCKED) + icon = ICON_LOCKED; + else + icon = ICON_UNLOCKED; + + uiBlockSetEmboss(block, UI_EMBOSSN); + but = uiDefIconButR(block, ICONTOG, 1, icon, + v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD, y - UI_UNIT_Y / 2.0f, + UI_UNIT_X, UI_UNIT_Y, &ptr, "lock", 0, 0, 0, 0, 0, NULL); + uiBlockSetEmboss(block, UI_EMBOSS); + } + + /* adjust y-position for next one */ + y -= CHANNEL_STEP; + } + glDisable(GL_BLEND); + + uiEndBlock(C, block); + uiDrawBlock(C, block); +} diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c new file mode 100644 index 00000000000..2225f01afe3 --- /dev/null +++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c @@ -0,0 +1,166 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_clip/clip_graph_ops.c + * \ingroup spclip + */ + +#include "DNA_object_types.h" /* SELECT */ +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_listbase.h" +#include "BLI_rect.h" + +#include "BKE_context.h" +#include "BKE_movieclip.h" +#include "BKE_tracking.h" +#include "BKE_depsgraph.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_clip.h" + +#include "UI_interface.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "UI_view2d.h" + +#include "clip_intern.h" // own include + +static int ED_space_clip_dopesheet_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc && sc->clip) { + if (sc->view == SC_VIEW_DOPESHEET) { + ARegion *ar = CTX_wm_region(C); + + return ar->regiontype == RGN_TYPE_PREVIEW; + } + } + + return FALSE; +} + +/********************** select channel operator *********************/ + +static int dopesheet_select_channel_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc && sc->clip) + return sc->view == SC_VIEW_DOPESHEET; + + return FALSE; +} + +static int dopesheet_select_channel_exec(bContext *C, wmOperator *op) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip(sc); + MovieTracking *tracking = &clip->tracking; + ListBase *tracksbase = BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *track; + float location[2]; + int extend = RNA_boolean_get(op->ptr, "extend"), channel, channel_index; + + RNA_float_get_array(op->ptr, "location", location); + channel = -(location[1] - (CHANNEL_FIRST + CHANNEL_HEIGHT_HALF)) / CHANNEL_STEP; + + for (track = tracksbase->first, channel_index = 0; track; track = track->next) { + if (!TRACK_VIEW_SELECTED(sc, track)) + continue; + + if (channel_index == channel) { + if (extend) + track->flag ^= TRACK_DOPE_SEL; + else + track->flag |= TRACK_DOPE_SEL; + + if (track->flag & TRACK_DOPE_SEL) { + MovieTrackingMarker *marker; + + /* make last selected in dopesheet track active in clip editor */ + tracking->act_track = track; + + /* make active track be centered to screen */ + /* XXX: doesn't work in other opened spaces */ + marker = BKE_tracking_get_marker(track, sc->user.framenr); + clip_view_center_to_point(sc, marker->pos[0], marker->pos[1]); + } + } + else if (!extend) + track->flag &= ~TRACK_DOPE_SEL; + + channel_index++; + } + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL); + + return OPERATOR_FINISHED; +} + +static int dopesheet_select_channel_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + float location[2]; + + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]); + RNA_float_set_array(op->ptr, "location", location); + + return dopesheet_select_channel_exec(C, op); +} + +void CLIP_OT_dopesheet_select_channel(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Channel"; + ot->description = "Select movie tracking channel"; + ot->idname = "CLIP_OT_dopesheet_select_channel"; + + /* api callbacks */ + ot->invoke = dopesheet_select_channel_invoke; + ot->exec = dopesheet_select_channel_exec; + ot->poll = dopesheet_select_channel_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, + "Location", "Mouse location to select channel", -100.0f, 100.0f); + RNA_def_boolean(ot->srna, "extend", 0, + "Extend", "Extend selection rather than clearing the existing selection"); +} diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 40be2622f95..099c3c7532c 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -70,13 +70,38 @@ int ED_space_clip_poll(bContext *C) return FALSE; } -void ED_space_clip_set(bContext *C, SpaceClip *sc, MovieClip *clip) +void ED_space_clip_set(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip) { + MovieClip *old_clip; + + if (!screen && C) + screen = CTX_wm_screen(C); + + old_clip = sc->clip; sc->clip = clip; if (sc->clip && sc->clip->id.us==0) sc->clip->id.us = 1; + if (screen) { + ScrArea *area; + SpaceLink *sl; + + for (area = screen->areabase.first; area; area = area->next) { + for (sl = area->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { + SpaceClip *cur_sc = (SpaceClip *) sl; + + if (cur_sc != sc) { + if (cur_sc->clip == old_clip || cur_sc->clip == NULL) { + cur_sc->clip = clip; + } + } + } + } + } + } + if (C) WM_event_add_notifier(C, NC_MOVIECLIP|NA_SELECTED, sc->clip); } diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index df14491c9c9..4825403fb4a 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -87,60 +87,6 @@ static void draw_curve_knot(float x, float y, float xscale, float yscale, float glPopMatrix(); } -static void draw_graph_cfra(SpaceClip *sc, ARegion *ar, Scene *scene) -{ - View2D *v2d = &ar->v2d; - float xscale, yscale; - float vec[2]; - - /* Draw a light green line to indicate current frame */ - vec[0] = (float)(sc->user.framenr * scene->r.framelen); - - UI_ThemeColor(TH_CFRAME); - glLineWidth(2.0); - - glBegin(GL_LINE_STRIP); - vec[1] = v2d->cur.ymin; - glVertex2fv(vec); - - vec[1] = v2d->cur.ymax; - glVertex2fv(vec); - glEnd(); - - glLineWidth(1.0); - - UI_view2d_view_orthoSpecial(ar, v2d, 1); - - /* because the frame number text is subject to the same scaling as the contents of the view */ - UI_view2d_getscale(v2d, &xscale, &yscale); - glScalef(1.0f/xscale, 1.0f, 1.0f); - - clip_draw_curfra_label(sc, (float)sc->user.framenr * xscale, 18); - - /* restore view transform */ - glScalef(xscale, 1.0, 1.0); -} - -static void draw_graph_sfra_efra(Scene *scene, View2D *v2d) -{ - UI_view2d_view_ortho(v2d); - - /* currently clip editor supposes that editing clip length is equal to scene frame range */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); - - glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); - glRectf((float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); - glDisable(GL_BLEND); - - UI_ThemeColorShade(TH_BACK, -60); - - /* thin lines where the actual frames are */ - fdrawline((float)SFRA, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); - fdrawline((float)EFRA, v2d->cur.ymin, (float)EFRA, v2d->cur.ymax); -} - static void tracking_segment_point_cb(void *UNUSED(userdata), MovieTrackingTrack *UNUSED(track), MovieTrackingMarker *marker, int UNUSED(coord), float val) { @@ -280,8 +226,8 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene) } /* frame range */ - draw_graph_sfra_efra(scene, v2d); + clip_draw_sfra_efra(v2d, scene); /* current frame */ - draw_graph_cfra(sc, ar, scene); + clip_draw_cfra(sc, ar, scene); } diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index f8c81c2944a..a71d7f4e70a 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -66,12 +66,14 @@ static int ED_space_clip_graph_poll(bContext *C) SpaceClip *sc = CTX_wm_space_clip(C); if (sc && sc->clip) { - ARegion *ar = CTX_wm_region(C); + if (sc->view == SC_VIEW_GRAPH) { + ARegion *ar = CTX_wm_region(C); - return ar->regiontype == RGN_TYPE_PREVIEW; + return ar->regiontype == RGN_TYPE_PREVIEW; + } } - return 0; + return FALSE; } typedef struct { @@ -233,8 +235,8 @@ static int mouse_select_curve(bContext *C, float co[2], int extend) tracking->act_track = userdata.track; /* make active track be centered to screen */ + /* XXX: doesn't work in other opened spaces */ marker = BKE_tracking_get_marker(userdata.track, sc->user.framenr); - clip_view_center_to_point(sc, marker->pos[0], marker->pos[1]); /* deselect all knots on newly selected curve */ diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 425a1da9ec5..679230f0b53 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -38,14 +38,36 @@ struct MovieClip; struct MovieTrackingMarker; struct MovieTrackingTrack; struct Scene; +struct ScrArea; struct SpaceClip; struct wmOperatorType; +/* channel heights */ +#define CHANNEL_FIRST -UI_UNIT_Y +#define CHANNEL_HEIGHT UI_UNIT_Y +#define CHANNEL_HEIGHT_HALF (UI_UNIT_Y / 2.0f) +#define CHANNEL_SKIP 2 +#define CHANNEL_STEP (CHANNEL_HEIGHT + CHANNEL_SKIP) + +#define CHANNEL_PAD 4 + +/* extra padding for lengths (to go under scrollers) */ +#define EXTRA_SCROLL_PAD 100.0f + +#define STRIP_HEIGHT_HALF 5 + /* internal exports only */ /* clip_buttons.c */ void ED_clip_buttons_register(struct ARegionType *art); +/* clip_dopesheet_draw.c */ +void clip_draw_dopesheet_main(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scene); +void clip_draw_dopesheet_channels(const struct bContext *C, struct ARegion *ar); + +/* clip_dopesheet_ops.c */ +void CLIP_OT_dopesheet_select_channel(struct wmOperatorType *ot); + /* clip_draw.c */ void clip_draw_main(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scene); void clip_draw_grease_pencil(struct bContext *C, int onlyv2d); @@ -81,6 +103,7 @@ void CLIP_OT_rebuild_proxy(struct wmOperatorType *ot); void CLIP_OT_mode_set(struct wmOperatorType *ot); /* clip_toolbar.c */ +struct ARegion *ED_clip_has_properties_region(struct ScrArea *sa); void CLIP_OT_tools(struct wmOperatorType *ot); void CLIP_OT_properties(struct wmOperatorType *ot); void ED_clip_tool_props_register(struct ARegionType *art); @@ -104,6 +127,9 @@ void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct ListB void clip_view_center_to_point(struct SpaceClip *sc, float x, float y); +void clip_draw_cfra(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scene); +void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene); + /* tracking_ops.c */ void CLIP_OT_select(struct wmOperatorType *ot); void CLIP_OT_select_all(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 7e1bbc254e9..5535fe268ae 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -184,7 +184,7 @@ static int open_exec(bContext *C, wmOperator *op) RNA_property_update(C, &pprop->ptr, pprop->prop); } else if (sc) { - ED_space_clip_set(C, sc, clip); + ED_space_clip_set(C, NULL, sc, clip); } WM_event_add_notifier(C, NC_MOVIECLIP|NA_ADDED, clip); diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c index b80deb8260a..da8bf8fedd9 100644 --- a/source/blender/editors/space_clip/clip_toolbar.c +++ b/source/blender/editors/space_clip/clip_toolbar.c @@ -56,7 +56,7 @@ /************************** properties ******************************/ -static ARegion *clip_has_properties_region(ScrArea *sa) +ARegion *ED_clip_has_properties_region(ScrArea *sa) { ARegion *ar, *arnew; @@ -90,9 +90,9 @@ static int properties_poll(bContext *C) static int properties_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *sa = CTX_wm_area(C); - ARegion *ar = clip_has_properties_region(sa); + ARegion *ar = ED_clip_has_properties_region(sa); - if (ar) + if (ar && ar->alignment != RGN_ALIGN_NONE) ED_region_toggle_hidden(C, ar); return OPERATOR_FINISHED; @@ -167,7 +167,7 @@ static int tools_exec(bContext *C, wmOperator *UNUSED(op)) ScrArea *sa = CTX_wm_area(C); ARegion *ar = clip_has_tools_region(sa); - if (ar) + if (ar && ar->alignment != RGN_ALIGN_NONE) ED_region_toggle_hidden(C, ar); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 443a1d0cdd3..c8ba8be7eae 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -29,6 +29,7 @@ * \ingroup spclip */ +#include "DNA_scene_types.h" #include "DNA_object_types.h" /* SELECT */ #include "MEM_guardedalloc.h" @@ -42,6 +43,9 @@ #include "BKE_tracking.h" #include "BKE_depsgraph.h" +#include "BIF_gl.h" +#include "BIF_glutil.h" + #include "WM_api.h" #include "WM_types.h" @@ -53,6 +57,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "UI_interface.h" +#include "UI_resources.h" #include "UI_view2d.h" #include "clip_intern.h" // own include @@ -220,3 +226,57 @@ void clip_view_center_to_point(SpaceClip *sc, float x, float y) sc->xof = (x - 0.5f) * width * aspx; sc->yof = (y - 0.5f) * height * aspy; } + +void clip_draw_cfra(SpaceClip *sc, ARegion *ar, Scene *scene) +{ + View2D *v2d = &ar->v2d; + float xscale, yscale; + float vec[2]; + + /* Draw a light green line to indicate current frame */ + vec[0] = (float)(sc->user.framenr * scene->r.framelen); + + UI_ThemeColor(TH_CFRAME); + glLineWidth(2.0); + + glBegin(GL_LINE_STRIP); + vec[1] = v2d->cur.ymin; + glVertex2fv(vec); + + vec[1] = v2d->cur.ymax; + glVertex2fv(vec); + glEnd(); + + glLineWidth(1.0); + + UI_view2d_view_orthoSpecial(ar, v2d, 1); + + /* because the frame number text is subject to the same scaling as the contents of the view */ + UI_view2d_getscale(v2d, &xscale, &yscale); + glScalef(1.0f/xscale, 1.0f, 1.0f); + + clip_draw_curfra_label(sc, (float)sc->user.framenr * xscale, 18); + + /* restore view transform */ + glScalef(xscale, 1.0, 1.0); +} + +void clip_draw_sfra_efra(View2D *v2d, Scene *scene) +{ + UI_view2d_view_ortho(v2d); + + /* currently clip editor supposes that editing clip length is equal to scene frame range */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + + glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); + glRectf((float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + glDisable(GL_BLEND); + + UI_ThemeColorShade(TH_BACK, -60); + + /* thin lines where the actual frames are */ + fdrawline((float)SFRA, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); + fdrawline((float)EFRA, v2d->cur.ymin, (float)EFRA, v2d->cur.ymax); +} diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 60322098250..c799a936480 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -72,31 +72,79 @@ static void init_preview_region(const bContext *C, ARegion *ar) { Scene *scene = CTX_data_scene(C); + ScrArea *sa = CTX_wm_area(C); + SpaceClip *sc = CTX_wm_space_clip(C); ar->regiontype = RGN_TYPE_PREVIEW; ar->alignment = RGN_ALIGN_TOP; ar->flag |= RGN_FLAG_HIDDEN; - ar->v2d.tot.xmin = 0.0f; - ar->v2d.tot.ymin = -10.0f; - ar->v2d.tot.xmax = (float)scene->r.efra; - ar->v2d.tot.ymax = 10.0f; + if (sc->view == SC_VIEW_DOPESHEET) { + ar->v2d.tot.xmin = -10.0f; + ar->v2d.tot.ymin = (float)(-sa->winy)/3.0f; + ar->v2d.tot.xmax = (float)(sa->winx); + ar->v2d.tot.ymax = 0.0f; - ar->v2d.cur = ar->v2d.tot; + ar->v2d.cur = ar->v2d.tot; - ar->v2d.min[0] = FLT_MIN; - ar->v2d.min[1] = FLT_MIN; + ar->v2d.min[0] = 0.0f; + ar->v2d.min[1] = 0.0f; - ar->v2d.max[0] = MAXFRAMEF; - ar->v2d.max[1] = FLT_MAX; + ar->v2d.max[0] = MAXFRAMEF; + ar->v2d.max[1] = FLT_MAX; - ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL); - ar->v2d.scroll |= (V2D_SCROLL_LEFT|V2D_SCROLL_SCALE_VERTICAL); + ar->v2d.minzoom = 0.01f; + ar->v2d.maxzoom = 50; + ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll |= (V2D_SCROLL_RIGHT); + ar->v2d.keepzoom = V2D_LOCKZOOM_Y; + ar->v2d.keepofs = V2D_KEEPOFS_Y; + ar->v2d.align = V2D_ALIGN_NO_POS_Y; + ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + } + else { + ar->v2d.tot.xmin = 0.0f; + ar->v2d.tot.ymin = -10.0f; + ar->v2d.tot.xmax = (float)scene->r.efra; + ar->v2d.tot.ymax = 10.0f; - ar->v2d.keeptot = 0; + ar->v2d.cur = ar->v2d.tot; + + ar->v2d.min[0] = FLT_MIN; + ar->v2d.min[1] = FLT_MIN; + + ar->v2d.max[0] = MAXFRAMEF; + ar->v2d.max[1] = FLT_MAX; + + ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll |= (V2D_SCROLL_LEFT|V2D_SCROLL_SCALE_VERTICAL); + + ar->v2d.minzoom = 0.0f; + ar->v2d.maxzoom = 0.0f; + ar->v2d.keepzoom = 0; + ar->v2d.keepofs = 0; + ar->v2d.align = 0; + ar->v2d.flag = 0; + + ar->v2d.keeptot = 0; + } } -static ARegion *clip_has_preview_region(const bContext *C, ScrArea *sa) +static void reinit_preview_region(const bContext *C, ARegion *ar) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc->view == SC_VIEW_DOPESHEET) { + if ((ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) == 0) + init_preview_region(C, ar); + } + else { + if (ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) + init_preview_region(C, ar); + } +} + +static ARegion *ED_clip_has_preview_region(const bContext *C, ScrArea *sa) { ARegion *ar, *arnew; @@ -119,6 +167,33 @@ static ARegion *clip_has_preview_region(const bContext *C, ScrArea *sa) return arnew; } +static ARegion *ED_clip_has_channels_region(ScrArea *sa) +{ + ARegion *ar, *arnew; + + ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS); + if (ar) + return ar; + + /* add subdiv level; after header */ + ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW); + + /* is error! */ + if (ar == NULL) + return NULL; + + arnew = MEM_callocN(sizeof(ARegion), "clip channels region"); + + BLI_insertlinkbefore(&sa->regionbase, ar, arnew); + arnew->regiontype = RGN_TYPE_CHANNELS; + arnew->alignment = RGN_ALIGN_LEFT; + + arnew->v2d.scroll = V2D_SCROLL_BOTTOM; + arnew->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + + return arnew; +} + static void clip_scopes_tag_refresh(ScrArea *sa) { SpaceClip *sc = (SpaceClip *)sa->spacedata.first; @@ -190,6 +265,16 @@ static SpaceLink *clip_new(const bContext *C) ar->regiontype = RGN_TYPE_UI; ar->alignment = RGN_ALIGN_RIGHT; + /* channels view */ + ar = MEM_callocN(sizeof(ARegion), "channels for clip"); + + BLI_addtail(&sc->regionbase, ar); + ar->regiontype = RGN_TYPE_CHANNELS; + ar->alignment = RGN_ALIGN_LEFT; + + ar->v2d.scroll = V2D_SCROLL_BOTTOM; + ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + /* preview view */ ar = MEM_callocN(sizeof(ARegion), "preview for clip"); @@ -394,6 +479,10 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_graph_center_current_frame); WM_operatortype_append(CLIP_OT_graph_disable_markers); + + /* ** clip_dopesheet_ops.c ** */ + + WM_operatortype_append(CLIP_OT_dopesheet_select_channel); } static void clip_keymap(struct wmKeyConfig *keyconf) @@ -612,6 +701,13 @@ static void clip_keymap(struct wmKeyConfig *keyconf) RNA_enum_set(kmi->ptr, "action", 2); /* toggle */ transform_keymap_for_space(keyconf, keymap, SPACE_CLIP); + + /* ******** Hotkeys avalaible for channels region only ******** */ + + keymap = WM_keymap_find(keyconf, "Clip Dopesheet Editor", SPACE_CLIP, 0); + + kmi = WM_keymap_add_item(keymap, "CLIP_OT_dopesheet_select_channel", ACTIONMOUSE, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "extend", TRUE); /* toggle */ } const char *clip_context_dir[]= {"edit_movieclip", NULL}; @@ -639,52 +735,190 @@ static void clip_refresh(const bContext *C, ScrArea *sa) Scene *scene = CTX_data_scene(C); SpaceClip *sc = (SpaceClip *)sa->spacedata.first; ARegion *ar_main = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - ARegion *ar_preview = clip_has_preview_region(C, sa); + ARegion *ar_tools = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS); + ARegion *ar_tool_props = BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS); + ARegion *ar_preview = ED_clip_has_preview_region(C, sa); + ARegion *ar_properties = ED_clip_has_properties_region(sa); + ARegion *ar_channels = ED_clip_has_channels_region(sa); + int main_visible = FALSE, preview_visible = FALSE, tools_visible = FALSE; + int tool_props_visible = FALSE, properties_visible = FALSE, channels_visible = FALSE; int view_changed = FALSE; switch (sc->view) { case SC_VIEW_CLIP: - if (ar_preview && !(ar_preview->flag & RGN_FLAG_HIDDEN)) { - ar_preview->flag |= RGN_FLAG_HIDDEN; - ar_preview->v2d.flag &= ~V2D_IS_INITIALISED; - WM_event_remove_handlers((bContext*)C, &ar_preview->handlers); - view_changed = TRUE; - } - if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) { - ar_main->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; - } - if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) { - /* store graph region align */ - if (ar_preview->alignment == RGN_ALIGN_TOP) - sc->runtime_flag &= ~SC_GRAPH_BOTTOM; - else - sc->runtime_flag |= SC_GRAPH_BOTTOM; - - ar_preview->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; - } + main_visible = TRUE; + preview_visible = FALSE; + tools_visible = TRUE; + tool_props_visible = TRUE; + properties_visible = TRUE; + channels_visible = FALSE; break; case SC_VIEW_GRAPH: - if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) { - ar_preview->flag &= ~RGN_FLAG_HIDDEN; - ar_preview->v2d.flag &= ~V2D_IS_INITIALISED; - ar_preview->v2d.cur = ar_preview->v2d.tot; - view_changed = TRUE; - } - if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) { - ar_main->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; - } - if (ar_preview && !ELEM(ar_preview->alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) { - if (sc->runtime_flag & SC_GRAPH_BOTTOM) - ar_preview->alignment = RGN_ALIGN_BOTTOM; - else - ar_preview->alignment = RGN_ALIGN_TOP; + main_visible = FALSE; + preview_visible = TRUE; + tools_visible = FALSE; + tool_props_visible = FALSE; + properties_visible = FALSE; + channels_visible = FALSE; - view_changed = TRUE; - } + reinit_preview_region(C, ar_preview); break; + case SC_VIEW_DOPESHEET: + main_visible = FALSE; + preview_visible = TRUE; + tools_visible = FALSE; + tool_props_visible = FALSE; + properties_visible = FALSE; + channels_visible = TRUE; + + reinit_preview_region(C, ar_preview); + break; + } + + if (main_visible) { + if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) { + ar_main->flag &= ~RGN_FLAG_HIDDEN; + ar_main->v2d.flag &= ~V2D_IS_INITIALISED; + view_changed = TRUE; + } + + if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) { + ar_main->alignment = RGN_ALIGN_NONE; + view_changed = TRUE; + } + } + else { + if (ar_main && !(ar_main->flag & RGN_FLAG_HIDDEN)) { + ar_main->flag |= RGN_FLAG_HIDDEN; + ar_main->v2d.flag &= ~V2D_IS_INITIALISED; + WM_event_remove_handlers((bContext *)C, &ar_main->handlers); + view_changed = TRUE; + } + if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) { + ar_main->alignment = RGN_ALIGN_NONE; + view_changed = TRUE; + } + } + + if (properties_visible) { + if (ar_properties && (ar_properties->flag & RGN_FLAG_HIDDEN)) { + ar_properties->flag &= ~RGN_FLAG_HIDDEN; + ar_properties->v2d.flag &= ~V2D_IS_INITIALISED; + view_changed = TRUE; + } + if (ar_properties && ar_properties->alignment != RGN_ALIGN_RIGHT) { + ar_properties->alignment = RGN_ALIGN_RIGHT; + view_changed = TRUE; + } + } + else { + if (ar_properties && !(ar_properties->flag & RGN_FLAG_HIDDEN)) { + ar_properties->flag |= RGN_FLAG_HIDDEN; + ar_properties->v2d.flag &= ~V2D_IS_INITIALISED; + WM_event_remove_handlers((bContext *)C, &ar_properties->handlers); + view_changed = TRUE; + } + if (ar_properties && ar_properties->alignment != RGN_ALIGN_NONE) { + ar_properties->alignment = RGN_ALIGN_NONE; + view_changed = TRUE; + } + } + + if (tools_visible) { + if (ar_tools && (ar_tools->flag & RGN_FLAG_HIDDEN)) { + ar_tools->flag &= ~RGN_FLAG_HIDDEN; + ar_tools->v2d.flag &= ~V2D_IS_INITIALISED; + view_changed = TRUE; + } + if (ar_tools && ar_tools->alignment != RGN_ALIGN_LEFT) { + ar_tools->alignment = RGN_ALIGN_LEFT; + view_changed = TRUE; + } + } + else { + if (ar_tools && !(ar_tools->flag & RGN_FLAG_HIDDEN)) { + ar_tools->flag |= RGN_FLAG_HIDDEN; + ar_tools->v2d.flag &= ~V2D_IS_INITIALISED; + WM_event_remove_handlers((bContext *)C, &ar_tools->handlers); + view_changed = TRUE; + } + if (ar_tools && ar_tools->alignment != RGN_ALIGN_NONE) { + ar_tools->alignment = RGN_ALIGN_NONE; + view_changed = TRUE; + } + } + + if (tool_props_visible) { + if (ar_tool_props && (ar_tool_props->flag & RGN_FLAG_HIDDEN)) { + ar_tool_props->flag &= ~RGN_FLAG_HIDDEN; + ar_tool_props->v2d.flag &= ~V2D_IS_INITIALISED; + view_changed = TRUE; + } + if (ar_tool_props && (ar_tool_props->alignment != (RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV))) { + ar_tool_props->alignment = RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV; + view_changed = TRUE; + } + } + else { + if (ar_tool_props && !(ar_tool_props->flag & RGN_FLAG_HIDDEN)) { + ar_tool_props->flag |= RGN_FLAG_HIDDEN; + ar_tool_props->v2d.flag &= ~V2D_IS_INITIALISED; + WM_event_remove_handlers((bContext *)C, &ar_tool_props->handlers); + view_changed = TRUE; + } + if (ar_tool_props && ar_tool_props->alignment != RGN_ALIGN_NONE) { + ar_tool_props->alignment = RGN_ALIGN_NONE; + view_changed = TRUE; + } + } + + if (preview_visible) { + if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) { + ar_preview->flag &= ~RGN_FLAG_HIDDEN; + ar_preview->v2d.flag &= ~V2D_IS_INITIALISED; + ar_preview->v2d.cur = ar_preview->v2d.tot; + view_changed = TRUE; + } + if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) { + ar_preview->alignment = RGN_ALIGN_NONE; + view_changed = TRUE; + } + } + else { + if (ar_preview && !(ar_preview->flag & RGN_FLAG_HIDDEN)) { + ar_preview->flag |= RGN_FLAG_HIDDEN; + ar_preview->v2d.flag &= ~V2D_IS_INITIALISED; + WM_event_remove_handlers((bContext *)C, &ar_preview->handlers); + view_changed = TRUE; + } + if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) { + ar_preview->alignment = RGN_ALIGN_NONE; + view_changed = TRUE; + } + } + + if (channels_visible) { + if (ar_channels && (ar_channels->flag & RGN_FLAG_HIDDEN)) { + ar_channels->flag &= ~RGN_FLAG_HIDDEN; + ar_channels->v2d.flag &= ~V2D_IS_INITIALISED; + view_changed = TRUE; + } + if (ar_channels && ar_channels->alignment != RGN_ALIGN_LEFT) { + ar_channels->alignment = RGN_ALIGN_LEFT; + view_changed = TRUE; + } + } + else { + if (ar_channels && !(ar_channels->flag & RGN_FLAG_HIDDEN)) { + ar_channels->flag |= RGN_FLAG_HIDDEN; + ar_channels->v2d.flag &= ~V2D_IS_INITIALISED; + WM_event_remove_handlers((bContext *)C, &ar_tools->handlers); + view_changed = TRUE; + } + if (ar_channels && ar_channels->alignment != RGN_ALIGN_NONE) { + ar_channels->alignment = RGN_ALIGN_NONE; + view_changed = TRUE; + } } if (view_changed) { @@ -835,13 +1069,13 @@ static void clip_preview_area_init(wmWindowManager *wm, ARegion *ar) WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } -static void clip_preview_area_draw(const bContext *C, ARegion *ar) +static void graph_area_draw(const bContext *C, ARegion *ar) { View2D *v2d = &ar->v2d; View2DScrollers *scrollers; SpaceClip *sc = CTX_wm_space_clip(C); Scene *scene = CTX_data_scene(C); - short unitx = V2D_UNIT_FRAMESCALE, unity = V2D_UNIT_VALUES; + short unitx, unity; if (sc->flag & SC_LOCK_TIMECURSOR) ED_clip_graph_center_current_frame(scene, ar); @@ -859,15 +1093,99 @@ static void clip_preview_area_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* scrollers */ + unitx = (sc->flag & SC_SHOW_SECONDS)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES; + unity = V2D_UNIT_VALUES; scrollers = UI_view2d_scrollers_calc(C, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP); UI_view2d_scrollers_draw(C, v2d, scrollers); UI_view2d_scrollers_free(scrollers); } +static void dopesheet_area_draw(const bContext *C, ARegion *ar) +{ + Scene *scene = CTX_data_scene(C); + SpaceClip *sc = CTX_wm_space_clip(C); + View2D *v2d = &ar->v2d; + View2DGrid *grid; + View2DScrollers *scrollers; + short unit = 0; + + /* clear and setup matrix */ + UI_ThemeClearColor(TH_BACK); + glClear(GL_COLOR_BUFFER_BIT); + + UI_view2d_view_ortho(v2d); + + /* time grid */ + unit = (sc->flag & SC_SHOW_SECONDS)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES; + grid = UI_view2d_grid_calc(CTX_data_scene(C), v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy); + UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL); + UI_view2d_grid_free(grid); + + /* data... */ + clip_draw_dopesheet_main(sc, ar, scene); + + /* reset view matrix */ + UI_view2d_view_restore(C); + + /* scrollers */ + scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + UI_view2d_scrollers_draw(C, v2d, scrollers); + UI_view2d_scrollers_free(scrollers); +} + +static void clip_preview_area_draw(const bContext *C, ARegion *ar) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc->view == SC_VIEW_GRAPH) + graph_area_draw(C, ar); + else if (sc->view == SC_VIEW_DOPESHEET) + dopesheet_area_draw(C, ar); +} + static void clip_preview_area_listener(ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn)) { } +/****************** channels region ******************/ + +static void clip_channels_area_init(wmWindowManager *wm, ARegion *ar) +{ + wmKeyMap *keymap; + + UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); + + keymap = WM_keymap_find(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); +} + +static void clip_channels_area_draw(const bContext *C, ARegion *ar) +{ + View2D *v2d = &ar->v2d; + View2DScrollers *scrollers; + + /* clear and setup matrix */ + UI_ThemeClearColor(TH_BACK); + glClear(GL_COLOR_BUFFER_BIT); + + UI_view2d_view_ortho(v2d); + + /* data... */ + clip_draw_dopesheet_channels(C, ar); + + /* reset view matrix */ + UI_view2d_view_restore(C); + + /* scrollers */ + scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + UI_view2d_scrollers_draw(C, v2d, scrollers); + UI_view2d_scrollers_free(scrollers); +} + +static void clip_channels_area_listener(ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn)) +{ +} + /****************** header region ******************/ /* add handlers, stuff you only do once or on area/region changes */ @@ -1045,4 +1363,15 @@ void ED_spacetype_clip(void) BLI_addhead(&st->regiontypes, art); BKE_spacetype_register(st); + + /* channels */ + art = MEM_callocN(sizeof(ARegionType), "spacetype clip channels region"); + art->regionid = RGN_TYPE_CHANNELS; + art->prefsizex = UI_COMPACT_PANEL_WIDTH; + art->keymapflag = ED_KEYMAP_FRAMES|ED_KEYMAP_UI; + art->listener = clip_channels_area_listener; + art->init = clip_channels_area_init; + art->draw = clip_channels_area_draw; + + BLI_addhead(&st->regiontypes, art); } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 958e8b44b9d..c2fbc611bc3 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -520,9 +520,8 @@ typedef struct SpaceClip { * defined when drawing and used for mouse position calculation */ /* movie postprocessing */ - int postproc_flag; + int postproc_flag, pad2; - int runtime_flag; /* different runtime flags */ void *draw_context; } SpaceClip; @@ -905,6 +904,7 @@ enum { #define SC_SHOW_GRAPH_TRACKS (1<<15) /*#define SC_SHOW_PYRAMID_LEVELS (1<<16) */ /* UNUSED */ #define SC_LOCK_TIMECURSOR (1<<17) +#define SC_SHOW_SECONDS (1<<18) /* SpaceClip->mode */ #define SC_MODE_TRACKING 0 @@ -914,6 +914,7 @@ enum { /* SpaceClip->view */ #define SC_VIEW_CLIP 0 #define SC_VIEW_GRAPH 1 +#define SC_VIEW_DOPESHEET 2 /* SpaceClip->runtime_flag */ #define SC_GRAPH_BOTTOM (1<<0) diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 2f099ed59f5..84d4215401b 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -230,6 +230,7 @@ enum { #define TRACK_CUSTOMCOLOR (1<<7) #define TRACK_USE_2D_STAB (1<<8) #define TRACK_PREVIEW_GRAYSCALE (1<<9) +#define TRACK_DOPE_SEL (1<<10) /* MovieTrackingTrack->tracker */ #define TRACKER_KLT 0 diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 84301c8000f..59061ac9a33 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -338,6 +338,7 @@ extern StructRNA RNA_MouseSensor; extern StructRNA RNA_MovieSequence; extern StructRNA RNA_MovieClipSequence; extern StructRNA RNA_MovieTrackingObject; +extern StructRNA RNA_MovieTrackingTrack; extern StructRNA RNA_MulticamSequence; extern StructRNA RNA_MultiresModifier; extern StructRNA RNA_MusgraveTexture; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 5e0a20c51ad..d1a776235c2 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1024,8 +1024,9 @@ static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C, static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, PointerRNA value) { SpaceClip *sc = (SpaceClip*)(ptr->data); + bScreen *screen = (bScreen*)ptr->id.data; - ED_space_clip_set(NULL, sc, (MovieClip*)value.data); + ED_space_clip_set(NULL, screen, sc, (MovieClip*)value.data); } static void rna_SpaceClipEditor_clip_mode_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -2930,6 +2931,7 @@ static void rna_def_space_clip(BlenderRNA *brna) static EnumPropertyItem view_items[] = { {SC_VIEW_CLIP, "CLIP", ICON_SEQUENCE, "Clip", "Show editing clip preview"}, {SC_VIEW_GRAPH, "GRAPH", ICON_IPO, "Graph", "Show graph view for active element"}, + {SC_VIEW_DOPESHEET, "DOPESHEET", ICON_ACTION, "Dopesheet", "Dopesheet view for tracking data"}, {0, NULL, 0, NULL, NULL}}; srna = RNA_def_struct(brna, "SpaceClipEditor", "Space"); @@ -3104,6 +3106,12 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "postproc_flag", MOVIECLIP_PREVIEW_GRAYSCALE); RNA_def_property_ui_text(prop, "Grayscale", "Display frame in grayscale mode"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); + + /* timeline */ + prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_SECONDS); + RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index dbe4aa47151..e63f05bd969 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2002,6 +2002,7 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Theme Clip Editor", "Theme settings for the Movie Clip Editor"); rna_def_userdef_theme_spaces_main(srna); + rna_def_userdef_theme_spaces_list_main(srna); prop = RNA_def_property(srna, "marker_outline", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "marker_outline"); @@ -2076,6 +2077,18 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna) RNA_def_property_range(prop, 0, 255); RNA_def_property_ui_text(prop, "Handle Vertex Size", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "strip"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Strips", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "strip_select"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Strips Selected", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_themes(BlenderRNA *brna) From 7d573d647247acff849757988b1eed2448533b2e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 16 Apr 2012 12:57:11 +0000 Subject: [PATCH 004/183] Cycles: add "Blur Glossy" integrator option. When using a value higher than 0.0, this will blur glossy reflections after blurry bounces, to reduce noise at the cost of accuracy. 1.0 is a good starting value to tweak. Some light paths have a low probability of being found while contributing much light to the pixel. As a result these light paths will be found in some pixels and not in others, causing fireflies. An example of such a difficult path might be a small light that is causing a small specular highlight on a sharp glossy material, which we are seeing through a rough glossy material. With path tracing it is difficult to find the specular highlight, but if we increase the roughness on the material the highlight gets bigger and softer, and so easier to find. Often this blurring will be hardly noticeable, because we are seeing it through a blurry material anyway, but there are also cases where this will lead to a loss of detail in lighting. (note that this is being committed to the tomato branch, mango will be using this branch until feature freeze for 2.63 is over, then switch back) --- intern/cycles/blender/addon/properties.py | 8 ++++---- intern/cycles/blender/addon/ui.py | 8 ++++---- intern/cycles/blender/blender_sync.cpp | 2 ++ intern/cycles/kernel/kernel_path.h | 17 ++++++++++++++++- intern/cycles/kernel/kernel_types.h | 4 +--- intern/cycles/render/integrator.cpp | 4 ++++ intern/cycles/render/integrator.h | 1 + 7 files changed, 32 insertions(+), 12 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index cb99ea3b499..9fc7ee5c88e 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -85,10 +85,10 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Leave out caustics, resulting in a darker image with less noise", default=False, ) - cls.blur_caustics = FloatProperty( - name="Blur Caustics", - description="Blur caustics to reduce noise", - min=0.0, max=1.0, + cls.blur_glossy = FloatProperty( + name="Blur Glossy", + description="Adaptively blur glossy shaders after blurry bounces, to reduce noise at the cost of accuracy", + min=0.0, max=10.0, default=0.0, ) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 4a8b639b390..9174e5a3bca 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -87,11 +87,11 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel): sub.prop(cscene, "diffuse_bounces", text="Diffuse") sub.prop(cscene, "glossy_bounces", text="Glossy") sub.prop(cscene, "transmission_bounces", text="Transmission") - sub.prop(cscene, "no_caustics") - #row = col.row() - #row.prop(cscene, "blur_caustics") - #row.active = not cscene.no_caustics + col.separator() + + col.prop(cscene, "no_caustics") + col.prop(cscene, "blur_glossy") class CyclesRender_PT_film(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 5a286298774..714110f8890 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -153,6 +153,8 @@ void BlenderSync::sync_integrator() integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows"); integrator->no_caustics = get_boolean(cscene, "no_caustics"); + integrator->blur_glossy = get_float(cscene, "blur_glossy"); + integrator->seed = get_int(cscene, "seed"); integrator->layer_flag = render_layer.layer; diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index ff12e85375c..ed47489de0e 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -223,6 +223,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R path_radiance_init(&L, kernel_data.film.use_light_pass); + float min_ray_pdf = FLT_MAX; float ray_pdf = 0.0f; PathState state; int rng_offset = PRNG_BASE_NUM; @@ -259,6 +260,18 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput); + /* blurring of bsdf after bounces, for rays that have a small likelihood + of following this particular path (diffuse, rough glossy) */ + if(kernel_data.integrator.blur_glossy != FLT_MAX) { + float blur_pdf = kernel_data.integrator.blur_glossy*min_ray_pdf; + + if(blur_pdf < 1.0f) { + float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f; + shader_bsdf_blur(kg, &sd, blur_roughness); + } + } + + /* holdout */ #ifdef __HOLDOUT__ if((sd.flag & SD_HOLDOUT) && (state.flag & PATH_RAY_CAMERA)) { float3 holdout_weight = shader_holdout_eval(kg, &sd); @@ -378,8 +391,10 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R path_radiance_bsdf_bounce(&L, &throughput, &bsdf_eval, bsdf_pdf, state.bounce, label); /* set labels */ - if(!(label & LABEL_TRANSPARENT)) + if(!(label & LABEL_TRANSPARENT)) { ray_pdf = bsdf_pdf; + min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf); + } /* update path state */ path_state_next(kg, &state, label); diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 391dcd12dad..3ba8356d296 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -516,6 +516,7 @@ typedef struct KernelIntegrator { /* caustics */ int no_caustics; + float blur_glossy; /* seed */ int seed; @@ -525,9 +526,6 @@ typedef struct KernelIntegrator { /* clamp */ float sample_clamp; - - /* padding */ - int pad; } KernelIntegrator; typedef struct KernelBVH { diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index 6e6d30f3879..f1fffcdbd74 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -41,6 +41,7 @@ Integrator::Integrator() transparent_shadows = false; no_caustics = false; + blur_glossy = 0.0f; seed = 0; layer_flag = ~0; sample_clamp = 0.0f; @@ -81,6 +82,8 @@ void Integrator::device_update(Device *device, DeviceScene *dscene) kintegrator->transparent_shadows = transparent_shadows; kintegrator->no_caustics = no_caustics; + kintegrator->blur_glossy = (blur_glossy == 0.0f)? FLT_MAX: 1.0f/blur_glossy; + kintegrator->seed = hash_int(seed); kintegrator->layer_flag = layer_flag << PATH_RAY_LAYER_SHIFT; @@ -119,6 +122,7 @@ bool Integrator::modified(const Integrator& integrator) transparent_probalistic == integrator.transparent_probalistic && transparent_shadows == integrator.transparent_shadows && no_caustics == integrator.no_caustics && + blur_glossy == integrator.blur_glossy && layer_flag == integrator.layer_flag && seed == integrator.seed && sample_clamp == integrator.sample_clamp); diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index abbbaca894c..6e292aeaf16 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -41,6 +41,7 @@ public: bool transparent_shadows; bool no_caustics; + float blur_glossy; int seed; int layer_flag; From cd78d3cdceae3f8659c3766767686897adb5d8a0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 17 Apr 2012 12:49:39 +0000 Subject: [PATCH 005/183] Cycles: render layer "Exclude Layers" added. Scene layers (all object that influence the render, directly or indirectly) are shared between all render layers. However sometimes it's useful to leave out some object influence for a particular render layer. That's what this option allows you to do. --- intern/cycles/blender/addon/ui.py | 14 ++++++++++---- intern/cycles/blender/blender_sync.cpp | 2 +- source/blender/makesdna/DNA_scene_types.h | 7 +++---- source/blender/makesrna/intern/rna_scene.c | 7 +++++++ source/blender/render/extern/include/RE_pipeline.h | 2 +- .../blender/render/intern/source/render_result.c | 1 + 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 9174e5a3bca..d981e661295 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -178,10 +178,7 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): col = split.column() col.prop(scene, "layers", text="Scene") - col.label(text="Material:") - col.prop(rl, "material_override", text="") - - col.prop(rl, "use_sky", "Use Environment") + col.prop(rl, "layers_exclude", text="Exclude") col = split.column() col.prop(rl, "layers", text="Layer") @@ -190,6 +187,15 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): split = layout.split() + col = split.column() + col.label(text="Material:") + col.prop(rl, "material_override", text="") + + col = split.column() + col.prop(rl, "use_sky", "Use Environment") + + split = layout.split() + col = split.column() col.label(text="Passes:") col.prop(rl, "use_pass_combined") diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 714110f8890..ff2b4135261 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -222,7 +222,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) { if((!layer && first_layer) || (layer && b_rlay->name() == layer)) { render_layer.name = b_rlay->name(); - render_layer.scene_layer = get_layer(b_scene.layers()); + render_layer.scene_layer = get_layer(b_scene.layers()) & ~get_layer(b_rlay->layers_exclude()); render_layer.layer = get_layer(b_rlay->layers()); render_layer.holdout_layer = get_layer(b_rlay->layers_zmask()); render_layer.layer |= render_layer.holdout_layer; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 79ed1186c1a..6a0a498742b 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -176,12 +176,11 @@ typedef struct SceneRenderLayer { struct Material *mat_override; struct Group *light_override; - unsigned int lay; /* scene->lay itself has priority over this */ - unsigned int lay_zmask; /* has to be after lay, this is for Z-masking */ + unsigned int lay; /* scene->lay itself has priority over this */ + unsigned int lay_zmask; /* has to be after lay, this is for Z-masking */ + unsigned int lay_exclude; /* not used by internal, exclude */ int layflag; - int pad; - int passflag; /* pass_xor has to be after passflag */ int pass_xor; } SceneRenderLayer; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 410756ff5ea..df8d11546b4 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1905,6 +1905,13 @@ void rna_def_render_layer_common(StructRNA *srna, int scene) if (scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "layers_exclude", PROP_BOOLEAN, PROP_LAYER); + RNA_def_property_boolean_sdna(prop, NULL, "lay_exclude", 1); + RNA_def_property_array(prop, 20); + RNA_def_property_ui_text(prop, "Exclude Layers", "Exclude scene layers from having any influence"); + if (scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); + else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + /* layer options */ prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "layflag", SCE_LAY_DISABLE); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 315995475e9..2a3c8e60638 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -82,7 +82,7 @@ typedef struct RenderLayer { /* copy of RenderData */ char name[RE_MAXNAME]; - unsigned int lay, lay_zmask; + unsigned int lay, lay_zmask, lay_exclude; int layflag, passflag, pass_xor; struct Material *mat_override; diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 37d6479e7bc..162fc160915 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -458,6 +458,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf BLI_strncpy(rl->name, srl->name, sizeof(rl->name)); rl->lay= srl->lay; rl->lay_zmask= srl->lay_zmask; + rl->lay_exclude= srl->lay_exclude; rl->layflag= srl->layflag; rl->passflag= srl->passflag; // for debugging: srl->passflag|SCE_PASS_RAYHITS; rl->pass_xor= srl->pass_xor; From cf6d854806860b4c3a29f5a7cd371e070c0aa14b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 18 Apr 2012 15:21:46 +0000 Subject: [PATCH 006/183] Cycles: environment pass will now render environment even if film is set to transparent. --- intern/cycles/kernel/kernel_accumulate.h | 9 +++++++-- intern/cycles/kernel/kernel_path.h | 16 ++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 9a52531eec0..6c3ade1c531 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -266,7 +266,7 @@ __device_inline void path_radiance_accum_background(PathRadiance *L, float3 thro #endif } -__device_inline float3 path_radiance_sum(PathRadiance *L) +__device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L) { #ifdef __PASSES__ if(L->use_light_pass) { @@ -283,9 +283,14 @@ __device_inline float3 path_radiance_sum(PathRadiance *L) L->indirect_glossy *= L->indirect; L->indirect_transmission *= L->indirect; - return L->emission + L->background + float3 L_sum = L->emission + L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission; + + if(!kernel_data.background.transparent) + L_sum += L->background; + + return L_sum; } else return L->emission; diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index ed47489de0e..20cba00aed8 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -240,13 +240,17 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R /* eval background shader if nothing hit */ if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) { L_transparent += average(throughput); + +#ifdef __PASSES__ + if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) +#endif + break; } + #ifdef __BACKGROUND__ - else { - /* sample background shader */ - float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf); - path_radiance_accum_background(&L, throughput, L_background, state.bounce); - } + /* sample background shader */ + float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf); + path_radiance_accum_background(&L, throughput, L_background, state.bounce); #endif break; @@ -409,7 +413,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R #endif } - float3 L_sum = path_radiance_sum(&L); + float3 L_sum = path_radiance_sum(kg, &L); #ifdef __CLAMP_SAMPLE__ path_radiance_clamp(&L, &L_sum, kernel_data.integrator.sample_clamp); From 27ffa5dfdf4eacc8bc933d58db33973950afeb7f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 18 Apr 2012 15:23:13 +0000 Subject: [PATCH 007/183] Cycles: per render layer Samples control, leaving it to 0 will use the common scene setting. --- intern/cycles/blender/addon/ui.py | 1 + intern/cycles/blender/blender_session.cpp | 7 ++++--- intern/cycles/blender/blender_sync.cpp | 2 ++ intern/cycles/blender/blender_sync.h | 5 ++++- source/blender/makesdna/DNA_scene_types.h | 3 +++ source/blender/makesrna/intern/rna_scene.c | 6 ++++++ 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index d981e661295..f934ba5a651 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -192,6 +192,7 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): col.prop(rl, "material_override", text="") col = split.column() + col.prop(rl, "samples") col.prop(rl, "use_sky", "Use Environment") split = layout.split() diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index dc6c69e2904..5ece7aa26e2 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -218,12 +218,13 @@ void BlenderSession::render() scene->film->passes = passes; scene->film->tag_update(scene); - /* update session */ - session->reset(buffer_params, session_params.samples); - /* update scene */ sync->sync_data(b_v3d, b_iter->name().c_str()); + /* update session */ + int samples = sync->get_layer_samples(); + session->reset(buffer_params, (samples == 0)? session_params.samples: samples); + /* render */ session->start(); session->wait(); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index ff2b4135261..0116422c756 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -210,6 +210,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) render_layer.holdout_layer = 0; render_layer.material_override = PointerRNA_NULL; render_layer.use_background = true; + render_layer.samples = 0; return; } } @@ -228,6 +229,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) render_layer.layer |= render_layer.holdout_layer; render_layer.material_override = b_rlay->material_override(); render_layer.use_background = b_rlay->use_sky(); + render_layer.samples = b_rlay->samples(); } first_layer = false; diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index d2550a1ffd7..ab8e4bd8d00 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -57,6 +57,7 @@ public: void sync_data(BL::SpaceView3D b_v3d, const char *layer = 0); void sync_camera(BL::Object b_override, int width, int height); void sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height); + int get_layer_samples() { return render_layer.samples; } /* get parameters */ static SceneParams get_scene_params(BL::Scene b_scene, bool background); @@ -108,7 +109,8 @@ private: RenderLayerInfo() : scene_layer(0), layer(0), holdout_layer(0), material_override(PointerRNA_NULL), - use_background(true) + use_background(true), + samples(0) {} string name; @@ -117,6 +119,7 @@ private: uint holdout_layer; BL::Material material_override; bool use_background; + int samples; } render_layer; }; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 6a0a498742b..f3109270ba8 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -183,6 +183,9 @@ typedef struct SceneRenderLayer { int passflag; /* pass_xor has to be after passflag */ int pass_xor; + + int samples; + int pad; } SceneRenderLayer; /* srl->layflag */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index df8d11546b4..3fc753d0578 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1912,6 +1912,12 @@ void rna_def_render_layer_common(StructRNA *srna, int scene) if (scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + if(scene) { + prop = RNA_def_property(srna, "samples", PROP_INT, PROP_UNSIGNED); + RNA_def_property_ui_text(prop, "Samples", "Override number of render samples for this render layer, 0 will use the scene setting"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + } + /* layer options */ prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "layflag", SCE_LAY_DISABLE); From 535cf658775d634125c40511df4712d1fd2d4cb0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 18 Apr 2012 16:11:48 +0000 Subject: [PATCH 008/183] Cycles: added a Normal output to the texture coordinate node. This currently gives the object space normal, which is the same under object animation. In the future this might become a "generated" normal so it's also stable for deforming objects, but for now it's already useful for non-deforming objects. --- intern/cycles/kernel/svm/svm_tex_coord.h | 27 + intern/cycles/kernel/svm/svm_types.h | 1 + intern/cycles/render/nodes.cpp | 7 + .../gpu/intern/gpu_shader_material.glsl | 5 +- .../gpu/intern/gpu_shader_material.glsl.c | 2921 +++++++++-------- .../shader/nodes/node_shader_tex_coord.c | 3 +- 6 files changed, 1502 insertions(+), 1462 deletions(-) diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index f494b6d66e1..98f8734aed2 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -40,6 +40,15 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack data = sd->P; break; } + case NODE_TEXCO_NORMAL: { + if(sd->object != ~0) { + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); + data = transform_direction(&tfm, sd->N); + } + else + data = sd->N; + break; + } case NODE_TEXCO_CAMERA: { Transform tfm = kernel_data.cam.worldtocamera; @@ -85,6 +94,15 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa data = sd->P + sd->dP.dx; break; } + case NODE_TEXCO_NORMAL: { + if(sd->object != ~0) { + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); + data = transform_direction(&tfm, sd->N); + } + else + data = sd->N; + break; + } case NODE_TEXCO_CAMERA: { Transform tfm = kernel_data.cam.worldtocamera; @@ -133,6 +151,15 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa data = sd->P + sd->dP.dy; break; } + case NODE_TEXCO_NORMAL: { + if(sd->object != ~0) { + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); + data = normalize(transform_direction(&tfm, sd->N)); + } + else + data = sd->N; + break; + } case NODE_TEXCO_CAMERA: { Transform tfm = kernel_data.cam.worldtocamera; diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 13d72307765..7ca852a24b6 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -119,6 +119,7 @@ typedef enum NodeLightPath { } NodeLightPath; typedef enum NodeTexCoord { + NODE_TEXCO_NORMAL, NODE_TEXCO_OBJECT, NODE_TEXCO_CAMERA, NODE_TEXCO_WINDOW, diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index db696993737..d71438ebae1 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1503,6 +1503,7 @@ TextureCoordinateNode::TextureCoordinateNode() { add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); add_output("Generated", SHADER_SOCKET_POINT); + add_output("Normal", SHADER_SOCKET_NORMAL); add_output("UV", SHADER_SOCKET_POINT); add_output("Object", SHADER_SOCKET_POINT); add_output("Camera", SHADER_SOCKET_POINT); @@ -1551,6 +1552,12 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler) } } + out = output("Normal"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(texco_node, NODE_TEXCO_NORMAL, out->stack_offset); + } + out = output("UV"); if(!out->links.empty()) { int attr = compiler.attribute(Attribute::STD_UV); diff --git a/source/blender/gpu/intern/gpu_shader_material.glsl b/source/blender/gpu/intern/gpu_shader_material.glsl index 2ac99e2eee2..76dacd4a10d 100644 --- a/source/blender/gpu/intern/gpu_shader_material.glsl +++ b/source/blender/gpu/intern/gpu_shader_material.glsl @@ -2041,12 +2041,13 @@ void node_geometry(vec3 I, vec3 N, mat4 toworld, backfacing = 0.0; } -void node_tex_coord(vec3 I, vec3 N, mat4 toworld, +void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec3 attr_orco, vec3 attr_uv, - out vec3 generated, out vec3 uv, out vec3 object, + out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, out vec3 camera, out vec3 window, out vec3 reflection) { generated = attr_orco; + normal = normalize((obinvmat*(viewinvmat*vec4(N, 0.0))).xyz); uv = attr_uv; object = I; camera = I; diff --git a/source/blender/gpu/intern/gpu_shader_material.glsl.c b/source/blender/gpu/intern/gpu_shader_material.glsl.c index a6d962a7bb9..6a6db7eadbb 100644 --- a/source/blender/gpu/intern/gpu_shader_material.glsl.c +++ b/source/blender/gpu/intern/gpu_shader_material.glsl.c @@ -1,1484 +1,1487 @@ /* DataToC output of file */ -int datatoc_gpu_shader_material_glsl_size= 49395; -char datatoc_gpu_shader_material_glsl[]= { - 10,102,108,111, 97,116, 32,101,120,112, 95, 98,108,101,110,100,101,114, 40, -102,108,111, 97,116, 32,102, 41, 10,123, 10, 9,114,101,116,117,114,110, 32,112,111,119, 40, 50, 46, 55, 49, 56, 50, 56, 49, 56, - 50, 56, 52, 54, 44, 32,102, 41, 59, 10,125, 10, 10,118,111,105,100, 32,114,103, 98, 95,116,111, 95,104,115,118, 40,118,101, 99, - 52, 32,114,103, 98, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, - 32, 99,109, 97,120, 44, 32, 99,109,105,110, 44, 32,104, 44, 32,115, 44, 32,118, 44, 32, 99,100,101,108,116, 97, 59, 10, 9,118, -101, 99, 51, 32, 99, 59, 10, 10, 9, 99,109, 97,120, 32, 61, 32,109, 97,120, 40,114,103, 98, 91, 48, 93, 44, 32,109, 97,120, 40, -114,103, 98, 91, 49, 93, 44, 32,114,103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,109,105,110, 32, 61, 32,109,105,110, 40,114,103, - 98, 91, 48, 93, 44, 32,109,105,110, 40,114,103, 98, 91, 49, 93, 44, 32,114,103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,100,101, -108,116, 97, 32, 61, 32, 99,109, 97,120, 45, 99,109,105,110, 59, 10, 10, 9,118, 32, 61, 32, 99,109, 97,120, 59, 10, 9,105,102, - 32, 40, 99,109, 97,120, 33, 61, 48, 46, 48, 41, 10, 9, 9,115, 32, 61, 32, 99,100,101,108,116, 97, 47, 99,109, 97,120, 59, 10, - 9,101,108,115,101, 32,123, 10, 9, 9,115, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, - 10, 10, 9,105,102, 32, 40,115, 32, 61, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, - 10, 9,101,108,115,101, 32,123, 10, 9, 9, 99, 32, 61, 32, 40,118,101, 99, 51, 40, 99,109, 97,120, 44, 32, 99,109, 97,120, 44, - 32, 99,109, 97,120, 41, 32, 45, 32,114,103, 98, 46,120,121,122, 41, 47, 99,100,101,108,116, 97, 59, 10, 10, 9, 9,105,102, 32, - 40,114,103, 98, 46,120, 61, 61, 99,109, 97,120, 41, 32,104, 32, 61, 32, 99, 91, 50, 93, 32, 45, 32, 99, 91, 49, 93, 59, 10, 9, - 9,101,108,115,101, 32,105,102, 32, 40,114,103, 98, 46,121, 61, 61, 99,109, 97,120, 41, 32,104, 32, 61, 32, 50, 46, 48, 32, 43, - 32, 99, 91, 48, 93, 32, 45, 32, 32, 99, 91, 50, 93, 59, 10, 9, 9,101,108,115,101, 32,104, 32, 61, 32, 52, 46, 48, 32, 43, 32, - 99, 91, 49, 93, 32, 45, 32, 99, 91, 48, 93, 59, 10, 10, 9, 9,104, 32, 47, 61, 32, 54, 46, 48, 59, 10, 10, 9, 9,105,102, 32, - 40,104, 60, 48, 46, 48, 41, 10, 9, 9, 9,104, 32, 43, 61, 32, 49, 46, 48, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, - 32, 61, 32,118,101, 99, 52, 40,104, 44, 32,115, 44, 32,118, 44, 32,114,103, 98, 46,119, 41, 59, 10,125, 10, 10,118,111,105,100, - 32,104,115,118, 95,116,111, 95,114,103, 98, 40,118,101, 99, 52, 32,104,115,118, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111, -117,116, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,105, 44, 32,102, 44, 32,112, 44, 32,113, 44, 32,116, 44, 32,104, - 44, 32,115, 44, 32,118, 59, 10, 9,118,101, 99, 51, 32,114,103, 98, 59, 10, 10, 9,104, 32, 61, 32,104,115,118, 91, 48, 93, 59, - 10, 9,115, 32, 61, 32,104,115,118, 91, 49, 93, 59, 10, 9,118, 32, 61, 32,104,115,118, 91, 50, 93, 59, 10, 10, 9,105,102, 40, -115, 61, 61, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, 32,118, 44, 32,118, 41, 59, - 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,105,102, 40,104, 61, 61, 49, 46, 48, 41, 10, 9, 9, 9,104, 32, 61, 32, - 48, 46, 48, 59, 10, 9, 9, 10, 9, 9,104, 32, 42, 61, 32, 54, 46, 48, 59, 10, 9, 9,105, 32, 61, 32,102,108,111,111,114, 40, -104, 41, 59, 10, 9, 9,102, 32, 61, 32,104, 32, 45, 32,105, 59, 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,102, 44, - 32,102, 44, 32,102, 41, 59, 10, 9, 9,112, 32, 61, 32,118, 42, 40, 49, 46, 48, 45,115, 41, 59, 10, 9, 9,113, 32, 61, 32,118, - 42, 40, 49, 46, 48, 45, 40,115, 42,102, 41, 41, 59, 10, 9, 9,116, 32, 61, 32,118, 42, 40, 49, 46, 48, 45, 40,115, 42, 40, 49, - 46, 48, 45,102, 41, 41, 41, 59, 10, 9, 9, 10, 9, 9,105,102, 32, 40,105, 32, 61, 61, 32, 48, 46, 48, 41, 32,114,103, 98, 32, - 61, 32,118,101, 99, 51, 40,118, 44, 32,116, 44, 32,112, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, - 32, 49, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,113, 44, 32,118, 44, 32,112, 41, 59, 10, 9, 9,101,108,115, -101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 50, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,112, 44, 32,118, 44, - 32,116, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 51, 46, 48, 41, 32,114,103, 98, 32, 61, 32, -118,101, 99, 51, 40,112, 44, 32,113, 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 52, - 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,116, 44, 32,112, 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32, -114,103, 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, 32,112, 44, 32,113, 41, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, - 32, 61, 32,118,101, 99, 52, 40,114,103, 98, 44, 32,104,115,118, 46,119, 41, 59, 10,125, 10, 10,102,108,111, 97,116, 32,115,114, -103, 98, 95,116,111, 95,108,105,110,101, 97,114,114,103, 98, 40,102,108,111, 97,116, 32, 99, 41, 10,123, 10, 9,105,102, 40, 99, - 32, 60, 32, 48, 46, 48, 52, 48, 52, 53, 41, 10, 9, 9,114,101,116,117,114,110, 32, 40, 99, 32, 60, 32, 48, 46, 48, 41, 63, 32, - 48, 46, 48, 58, 32, 99, 32, 42, 32, 40, 49, 46, 48, 47, 49, 50, 46, 57, 50, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,114,101, -116,117,114,110, 32,112,111,119, 40, 40, 99, 32, 43, 32, 48, 46, 48, 53, 53, 41, 42, 40, 49, 46, 48, 47, 49, 46, 48, 53, 53, 41, - 44, 32, 50, 46, 52, 41, 59, 10,125, 10, 10,102,108,111, 97,116, 32,108,105,110,101, 97,114,114,103, 98, 95,116,111, 95,115,114, -103, 98, 40,102,108,111, 97,116, 32, 99, 41, 10,123, 10, 9,105,102, 40, 99, 32, 60, 32, 48, 46, 48, 48, 51, 49, 51, 48, 56, 41, - 10, 9, 9,114,101,116,117,114,110, 32, 40, 99, 32, 60, 32, 48, 46, 48, 41, 63, 32, 48, 46, 48, 58, 32, 99, 32, 42, 32, 49, 50, - 46, 57, 50, 59, 10, 9,101,108,115,101, 10, 9, 9,114,101,116,117,114,110, 32, 49, 46, 48, 53, 53, 32, 42, 32,112,111,119, 40, - 99, 44, 32, 49, 46, 48, 47, 50, 46, 52, 41, 32, 45, 32, 48, 46, 48, 53, 53, 59, 10,125, 10, 10,118,111,105,100, 32,115,114,103, - 98, 95,116,111, 95,108,105,110,101, 97,114,114,103, 98, 40,118,101, 99, 52, 32, 99,111,108, 95,102,114,111,109, 44, 32,111,117, -116, 32,118,101, 99, 52, 32, 99,111,108, 95,116,111, 41, 10,123, 10, 9, 99,111,108, 95,116,111, 46,114, 32, 61, 32,115,114,103, - 98, 95,116,111, 95,108,105,110,101, 97,114,114,103, 98, 40, 99,111,108, 95,102,114,111,109, 46,114, 41, 59, 10, 9, 99,111,108, - 95,116,111, 46,103, 32, 61, 32,115,114,103, 98, 95,116,111, 95,108,105,110,101, 97,114,114,103, 98, 40, 99,111,108, 95,102,114, -111,109, 46,103, 41, 59, 10, 9, 99,111,108, 95,116,111, 46, 98, 32, 61, 32,115,114,103, 98, 95,116,111, 95,108,105,110,101, 97, -114,114,103, 98, 40, 99,111,108, 95,102,114,111,109, 46, 98, 41, 59, 10, 9, 99,111,108, 95,116,111, 46, 97, 32, 61, 32, 99,111, -108, 95,102,114,111,109, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,108,105,110,101, 97,114,114,103, 98, 95,116,111, 95,115, -114,103, 98, 40,118,101, 99, 52, 32, 99,111,108, 95,102,114,111,109, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108, 95, -116,111, 41, 10,123, 10, 9, 99,111,108, 95,116,111, 46,114, 32, 61, 32,108,105,110,101, 97,114,114,103, 98, 95,116,111, 95,115, -114,103, 98, 40, 99,111,108, 95,102,114,111,109, 46,114, 41, 59, 10, 9, 99,111,108, 95,116,111, 46,103, 32, 61, 32,108,105,110, -101, 97,114,114,103, 98, 95,116,111, 95,115,114,103, 98, 40, 99,111,108, 95,102,114,111,109, 46,103, 41, 59, 10, 9, 99,111,108, - 95,116,111, 46, 98, 32, 61, 32,108,105,110,101, 97,114,114,103, 98, 95,116,111, 95,115,114,103, 98, 40, 99,111,108, 95,102,114, -111,109, 46, 98, 41, 59, 10, 9, 99,111,108, 95,116,111, 46, 97, 32, 61, 32, 99,111,108, 95,102,114,111,109, 46, 97, 59, 10,125, - 10, 10, 35,100,101,102,105,110,101, 32, 77, 95, 80, 73, 32, 51, 46, 49, 52, 49, 53, 57, 50, 54, 53, 51, 53, 56, 57, 55, 57, 51, - 50, 51, 56, 52, 54, 10, 35,100,101,102,105,110,101, 32, 77, 95, 49, 95, 80, 73, 32, 48, 46, 51, 49, 56, 51, 48, 57, 56, 56, 54, - 49, 56, 51, 55, 57, 48, 54, 57, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 83, 72, 65, 68, 69, 82, 32, 78, 79, - 68, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, 32,118, 99,111,108, 95, - 97,116,116,114,105, 98,117,116,101, 40,118,101, 99, 52, 32, 97,116,116,118, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, - 32,118, 99,111,108, 41, 10,123, 10, 9,118, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 97,116,116,118, 99,111,108, 46,120, 47, - 50, 53, 53, 46, 48, 44, 32, 97,116,116,118, 99,111,108, 46,121, 47, 50, 53, 53, 46, 48, 44, 32, 97,116,116,118, 99,111,108, 46, -122, 47, 50, 53, 53, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,117,118, 95, 97,116,116,114,105, 98, -117,116,101, 40,118,101, 99, 50, 32, 97,116,116,117,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 41, 10,123, 10, 9, -117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 42, 50, 46, 48, 32, 45, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, - 49, 46, 48, 41, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,103,101,111,109, 40,118,101, 99, 51, 32, 99,111, - 44, 32,118,101, 99, 51, 32,110,111,114, 44, 32,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,118,101, 99, - 51, 32, 97,116,116,111,114, 99,111, 44, 32,118,101, 99, 50, 32, 97,116,116,117,118, 44, 32,118,101, 99, 52, 32, 97,116,116,118, - 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,103,108,111, 98, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108, -111, 99, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,114, - 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, - 44, 32,111,117,116, 32,118,101, 99, 52, 32,118, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 99,111,108, 95, - 97,108,112,104, 97, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102,114,111,110,116, 98, 97, 99,107, 41, 10,123, 10, 9,108, -111, 99, 97,108, 32, 61, 32, 99,111, 59, 10, 9,118,105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,111, 99, - 97,108, 41, 59, 10, 9,103,108,111, 98, 97,108, 32, 61, 32, 40,118,105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40, -108,111, 99, 97,108, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116,111,114, 99, -111, 59, 10, 9,117,118, 95, 97,116,116,114,105, 98,117,116,101, 40, 97,116,116,117,118, 44, 32,117,118, 41, 59, 10, 9,110,111, -114,109, 97,108, 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,110,111,114, 41, 59, 9, 47, 42, 32, 98,108,101,110,100, -101,114, 32,114,101,110,100,101,114, 32,110,111,114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9, -118, 99,111,108, 95, 97,116,116,114,105, 98,117,116,101, 40, 97,116,116,118, 99,111,108, 44, 32,118, 99,111,108, 41, 59, 10, 9, -118, 99,111,108, 95, 97,108,112,104, 97, 32, 61, 32, 97,116,116,118, 99,111,108, 46, 97, 59, 10, 9,102,114,111,110,116, 98, 97, - 99,107, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118, -101, 99, 44, 32,109, 97,116, 52, 32,109, 97,116, 44, 32,118,101, 99, 51, 32,109,105,110,118,101, 99, 44, 32,118,101, 99, 51, 32, -109, 97,120,118,101, 99, 44, 32,102,108,111, 97,116, 32,100,111,109,105,110, 44, 32,102,108,111, 97,116, 32,100,111,109, 97,120, - 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 40, -109, 97,116, 32, 42, 32,118,101, 99, 52, 40,118,101, 99, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9,105,102, 40,100, -111,109,105,110, 32, 61, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116,118,101, 99, 32, 61, 32,109, 97,120, 40,111,117,116,118, -101, 99, 44, 32,109,105,110,118,101, 99, 41, 59, 10, 9,105,102, 40,100,111,109, 97,120, 32, 61, 61, 32, 49, 46, 48, 41, 10, 9, - 9,111,117,116,118,101, 99, 32, 61, 32,109,105,110, 40,111,117,116,118,101, 99, 44, 32,109, 97,120,118,101, 99, 41, 59, 10,125, - 10, 10,118,111,105,100, 32, 99, 97,109,101,114, 97, 40,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32, -111,117,116,118,105,101,119, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,100,101,112,116,104, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,111,117,116,100,105,115,116, 41, 10,123, 10, 9,111,117,116,100,101,112,116,104, 32, 61, 32, 97, 98, -115, 40, 99,111, 46,122, 41, 59, 10, 9,111,117,116,100,105,115,116, 32, 61, 32,108,101,110,103,116,104, 40, 99,111, 41, 59, 10, - 9,111,117,116,118,105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 41, 59, 10,125, 10, 10,118,111,105, -100, 32,109, 97,116,104, 95, 97,100,100, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, - 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, - 32,118, 97,108, 49, 32, 43, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,115,117, 98,116,114, - 97, 99,116, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32, -102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 45, - 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109,117,108,116,105,112,108,121, 40,102,108,111, - 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111, -117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 42, 32,118, 97,108, 50, 59, 10, -125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,100,105,118,105,100,101, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32, -102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, - 9,105,102, 32, 40,118, 97,108, 50, 32, 61, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, - 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 47, 32,118, 97,108, 50, 59, 10, -125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,115,105,110,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,115,105,110, 40,118, - 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 99,111,115,105,110,101, 40,102,108,111, 97,116, 32,118, - 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, - 61, 32, 99,111,115, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,116, 97,110,103,101,110,116, +int datatoc_gpu_shader_material_glsl_size = 49493; +char datatoc_gpu_shader_material_glsl[] = { + 10,102,108,111, 97,116, 32,101,120,112, 95, 98,108,101,110,100,101,114, 40,102,108, +111, 97,116, 32,102, 41, 10,123, 10, 9,114,101,116,117,114,110, 32,112,111,119, 40, 50, 46, 55, 49, 56, 50, 56, 49, 56, 50, 56, + 52, 54, 44, 32,102, 41, 59, 10,125, 10, 10,118,111,105,100, 32,114,103, 98, 95,116,111, 95,104,115,118, 40,118,101, 99, 52, 32, +114,103, 98, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, 99, +109, 97,120, 44, 32, 99,109,105,110, 44, 32,104, 44, 32,115, 44, 32,118, 44, 32, 99,100,101,108,116, 97, 59, 10, 9,118,101, 99, + 51, 32, 99, 59, 10, 10, 9, 99,109, 97,120, 32, 61, 32,109, 97,120, 40,114,103, 98, 91, 48, 93, 44, 32,109, 97,120, 40,114,103, + 98, 91, 49, 93, 44, 32,114,103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,109,105,110, 32, 61, 32,109,105,110, 40,114,103, 98, 91, + 48, 93, 44, 32,109,105,110, 40,114,103, 98, 91, 49, 93, 44, 32,114,103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,100,101,108,116, + 97, 32, 61, 32, 99,109, 97,120, 45, 99,109,105,110, 59, 10, 10, 9,118, 32, 61, 32, 99,109, 97,120, 59, 10, 9,105,102, 32, 40, + 99,109, 97,120, 33, 61, 48, 46, 48, 41, 10, 9, 9,115, 32, 61, 32, 99,100,101,108,116, 97, 47, 99,109, 97,120, 59, 10, 9,101, +108,115,101, 32,123, 10, 9, 9,115, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 10, + 9,105,102, 32, 40,115, 32, 61, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9, +101,108,115,101, 32,123, 10, 9, 9, 99, 32, 61, 32, 40,118,101, 99, 51, 40, 99,109, 97,120, 44, 32, 99,109, 97,120, 44, 32, 99, +109, 97,120, 41, 32, 45, 32,114,103, 98, 46,120,121,122, 41, 47, 99,100,101,108,116, 97, 59, 10, 10, 9, 9,105,102, 32, 40,114, +103, 98, 46,120, 61, 61, 99,109, 97,120, 41, 32,104, 32, 61, 32, 99, 91, 50, 93, 32, 45, 32, 99, 91, 49, 93, 59, 10, 9, 9,101, +108,115,101, 32,105,102, 32, 40,114,103, 98, 46,121, 61, 61, 99,109, 97,120, 41, 32,104, 32, 61, 32, 50, 46, 48, 32, 43, 32, 99, + 91, 48, 93, 32, 45, 32, 32, 99, 91, 50, 93, 59, 10, 9, 9,101,108,115,101, 32,104, 32, 61, 32, 52, 46, 48, 32, 43, 32, 99, 91, + 49, 93, 32, 45, 32, 99, 91, 48, 93, 59, 10, 10, 9, 9,104, 32, 47, 61, 32, 54, 46, 48, 59, 10, 10, 9, 9,105,102, 32, 40,104, + 60, 48, 46, 48, 41, 10, 9, 9, 9,104, 32, 43, 61, 32, 49, 46, 48, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, 32, 61, + 32,118,101, 99, 52, 40,104, 44, 32,115, 44, 32,118, 44, 32,114,103, 98, 46,119, 41, 59, 10,125, 10, 10,118,111,105,100, 32,104, +115,118, 95,116,111, 95,114,103, 98, 40,118,101, 99, 52, 32,104,115,118, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, + 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,105, 44, 32,102, 44, 32,112, 44, 32,113, 44, 32,116, 44, 32,104, 44, 32, +115, 44, 32,118, 59, 10, 9,118,101, 99, 51, 32,114,103, 98, 59, 10, 10, 9,104, 32, 61, 32,104,115,118, 91, 48, 93, 59, 10, 9, +115, 32, 61, 32,104,115,118, 91, 49, 93, 59, 10, 9,118, 32, 61, 32,104,115,118, 91, 50, 93, 59, 10, 10, 9,105,102, 40,115, 61, + 61, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, 32,118, 44, 32,118, 41, 59, 10, 9, +125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,105,102, 40,104, 61, 61, 49, 46, 48, 41, 10, 9, 9, 9,104, 32, 61, 32, 48, 46, + 48, 59, 10, 9, 9, 10, 9, 9,104, 32, 42, 61, 32, 54, 46, 48, 59, 10, 9, 9,105, 32, 61, 32,102,108,111,111,114, 40,104, 41, + 59, 10, 9, 9,102, 32, 61, 32,104, 32, 45, 32,105, 59, 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,102, 44, 32,102, + 44, 32,102, 41, 59, 10, 9, 9,112, 32, 61, 32,118, 42, 40, 49, 46, 48, 45,115, 41, 59, 10, 9, 9,113, 32, 61, 32,118, 42, 40, + 49, 46, 48, 45, 40,115, 42,102, 41, 41, 59, 10, 9, 9,116, 32, 61, 32,118, 42, 40, 49, 46, 48, 45, 40,115, 42, 40, 49, 46, 48, + 45,102, 41, 41, 41, 59, 10, 9, 9, 10, 9, 9,105,102, 32, 40,105, 32, 61, 61, 32, 48, 46, 48, 41, 32,114,103, 98, 32, 61, 32, +118,101, 99, 51, 40,118, 44, 32,116, 44, 32,112, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 49, + 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,113, 44, 32,118, 44, 32,112, 41, 59, 10, 9, 9,101,108,115,101, 32, +105,102, 32, 40,105, 32, 61, 61, 32, 50, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,112, 44, 32,118, 44, 32,116, + 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 51, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, + 99, 51, 40,112, 44, 32,113, 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 52, 46, 48, + 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,116, 44, 32,112, 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32,114,103, + 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, 32,112, 44, 32,113, 41, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, 32, 61, + 32,118,101, 99, 52, 40,114,103, 98, 44, 32,104,115,118, 46,119, 41, 59, 10,125, 10, 10,102,108,111, 97,116, 32,115,114,103, 98, + 95,116,111, 95,108,105,110,101, 97,114,114,103, 98, 40,102,108,111, 97,116, 32, 99, 41, 10,123, 10, 9,105,102, 40, 99, 32, 60, + 32, 48, 46, 48, 52, 48, 52, 53, 41, 10, 9, 9,114,101,116,117,114,110, 32, 40, 99, 32, 60, 32, 48, 46, 48, 41, 63, 32, 48, 46, + 48, 58, 32, 99, 32, 42, 32, 40, 49, 46, 48, 47, 49, 50, 46, 57, 50, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,114,101,116,117, +114,110, 32,112,111,119, 40, 40, 99, 32, 43, 32, 48, 46, 48, 53, 53, 41, 42, 40, 49, 46, 48, 47, 49, 46, 48, 53, 53, 41, 44, 32, + 50, 46, 52, 41, 59, 10,125, 10, 10,102,108,111, 97,116, 32,108,105,110,101, 97,114,114,103, 98, 95,116,111, 95,115,114,103, 98, + 40,102,108,111, 97,116, 32, 99, 41, 10,123, 10, 9,105,102, 40, 99, 32, 60, 32, 48, 46, 48, 48, 51, 49, 51, 48, 56, 41, 10, 9, + 9,114,101,116,117,114,110, 32, 40, 99, 32, 60, 32, 48, 46, 48, 41, 63, 32, 48, 46, 48, 58, 32, 99, 32, 42, 32, 49, 50, 46, 57, + 50, 59, 10, 9,101,108,115,101, 10, 9, 9,114,101,116,117,114,110, 32, 49, 46, 48, 53, 53, 32, 42, 32,112,111,119, 40, 99, 44, + 32, 49, 46, 48, 47, 50, 46, 52, 41, 32, 45, 32, 48, 46, 48, 53, 53, 59, 10,125, 10, 10,118,111,105,100, 32,115,114,103, 98, 95, +116,111, 95,108,105,110,101, 97,114,114,103, 98, 40,118,101, 99, 52, 32, 99,111,108, 95,102,114,111,109, 44, 32,111,117,116, 32, +118,101, 99, 52, 32, 99,111,108, 95,116,111, 41, 10,123, 10, 9, 99,111,108, 95,116,111, 46,114, 32, 61, 32,115,114,103, 98, 95, +116,111, 95,108,105,110,101, 97,114,114,103, 98, 40, 99,111,108, 95,102,114,111,109, 46,114, 41, 59, 10, 9, 99,111,108, 95,116, +111, 46,103, 32, 61, 32,115,114,103, 98, 95,116,111, 95,108,105,110,101, 97,114,114,103, 98, 40, 99,111,108, 95,102,114,111,109, + 46,103, 41, 59, 10, 9, 99,111,108, 95,116,111, 46, 98, 32, 61, 32,115,114,103, 98, 95,116,111, 95,108,105,110,101, 97,114,114, +103, 98, 40, 99,111,108, 95,102,114,111,109, 46, 98, 41, 59, 10, 9, 99,111,108, 95,116,111, 46, 97, 32, 61, 32, 99,111,108, 95, +102,114,111,109, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,108,105,110,101, 97,114,114,103, 98, 95,116,111, 95,115,114,103, + 98, 40,118,101, 99, 52, 32, 99,111,108, 95,102,114,111,109, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108, 95,116,111, + 41, 10,123, 10, 9, 99,111,108, 95,116,111, 46,114, 32, 61, 32,108,105,110,101, 97,114,114,103, 98, 95,116,111, 95,115,114,103, + 98, 40, 99,111,108, 95,102,114,111,109, 46,114, 41, 59, 10, 9, 99,111,108, 95,116,111, 46,103, 32, 61, 32,108,105,110,101, 97, +114,114,103, 98, 95,116,111, 95,115,114,103, 98, 40, 99,111,108, 95,102,114,111,109, 46,103, 41, 59, 10, 9, 99,111,108, 95,116, +111, 46, 98, 32, 61, 32,108,105,110,101, 97,114,114,103, 98, 95,116,111, 95,115,114,103, 98, 40, 99,111,108, 95,102,114,111,109, + 46, 98, 41, 59, 10, 9, 99,111,108, 95,116,111, 46, 97, 32, 61, 32, 99,111,108, 95,102,114,111,109, 46, 97, 59, 10,125, 10, 10, + 35,100,101,102,105,110,101, 32, 77, 95, 80, 73, 32, 51, 46, 49, 52, 49, 53, 57, 50, 54, 53, 51, 53, 56, 57, 55, 57, 51, 50, 51, + 56, 52, 54, 10, 35,100,101,102,105,110,101, 32, 77, 95, 49, 95, 80, 73, 32, 48, 46, 51, 49, 56, 51, 48, 57, 56, 56, 54, 49, 56, + 51, 55, 57, 48, 54, 57, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 83, 72, 65, 68, 69, 82, 32, 78, 79, 68, 69, + 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, 32,118, 99,111,108, 95, 97,116, +116,114,105, 98,117,116,101, 40,118,101, 99, 52, 32, 97,116,116,118, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,118, + 99,111,108, 41, 10,123, 10, 9,118, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 97,116,116,118, 99,111,108, 46,120, 47, 50, 53, + 53, 46, 48, 44, 32, 97,116,116,118, 99,111,108, 46,121, 47, 50, 53, 53, 46, 48, 44, 32, 97,116,116,118, 99,111,108, 46,122, 47, + 50, 53, 53, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,117,118, 95, 97,116,116,114,105, 98,117,116, +101, 40,118,101, 99, 50, 32, 97,116,116,117,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 41, 10,123, 10, 9,117,118, + 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 42, 50, 46, 48, 32, 45, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, + 48, 41, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,103,101,111,109, 40,118,101, 99, 51, 32, 99,111, 44, 32, +118,101, 99, 51, 32,110,111,114, 44, 32,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, + 97,116,116,111,114, 99,111, 44, 32,118,101, 99, 50, 32, 97,116,116,117,118, 44, 32,118,101, 99, 52, 32, 97,116,116,118, 99,111, +108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,103,108,111, 98, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108,111, 99, + 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,114, 99,111, + 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32, +111,117,116, 32,118,101, 99, 52, 32,118, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 99,111,108, 95, 97,108, +112,104, 97, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102,114,111,110,116, 98, 97, 99,107, 41, 10,123, 10, 9,108,111, 99, + 97,108, 32, 61, 32, 99,111, 59, 10, 9,118,105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,111, 99, 97,108, + 41, 59, 10, 9,103,108,111, 98, 97,108, 32, 61, 32, 40,118,105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40,108,111, + 99, 97,108, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116,111,114, 99,111, 59, + 10, 9,117,118, 95, 97,116,116,114,105, 98,117,116,101, 40, 97,116,116,117,118, 44, 32,117,118, 41, 59, 10, 9,110,111,114,109, + 97,108, 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,110,111,114, 41, 59, 9, 47, 42, 32, 98,108,101,110,100,101,114, + 32,114,101,110,100,101,114, 32,110,111,114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9,118, 99, +111,108, 95, 97,116,116,114,105, 98,117,116,101, 40, 97,116,116,118, 99,111,108, 44, 32,118, 99,111,108, 41, 59, 10, 9,118, 99, +111,108, 95, 97,108,112,104, 97, 32, 61, 32, 97,116,116,118, 99,111,108, 46, 97, 59, 10, 9,102,114,111,110,116, 98, 97, 99,107, + 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118,101, 99, + 44, 32,109, 97,116, 52, 32,109, 97,116, 44, 32,118,101, 99, 51, 32,109,105,110,118,101, 99, 44, 32,118,101, 99, 51, 32,109, 97, +120,118,101, 99, 44, 32,102,108,111, 97,116, 32,100,111,109,105,110, 44, 32,102,108,111, 97,116, 32,100,111,109, 97,120, 44, 32, +111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 40,109, 97, +116, 32, 42, 32,118,101, 99, 52, 40,118,101, 99, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9,105,102, 40,100,111,109, +105,110, 32, 61, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116,118,101, 99, 32, 61, 32,109, 97,120, 40,111,117,116,118,101, 99, + 44, 32,109,105,110,118,101, 99, 41, 59, 10, 9,105,102, 40,100,111,109, 97,120, 32, 61, 61, 32, 49, 46, 48, 41, 10, 9, 9,111, +117,116,118,101, 99, 32, 61, 32,109,105,110, 40,111,117,116,118,101, 99, 44, 32,109, 97,120,118,101, 99, 41, 59, 10,125, 10, 10, +118,111,105,100, 32, 99, 97,109,101,114, 97, 40,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117, +116,118,105,101,119, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,100,101,112,116,104, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,111,117,116,100,105,115,116, 41, 10,123, 10, 9,111,117,116,100,101,112,116,104, 32, 61, 32, 97, 98,115, 40, + 99,111, 46,122, 41, 59, 10, 9,111,117,116,100,105,115,116, 32, 61, 32,108,101,110,103,116,104, 40, 99,111, 41, 59, 10, 9,111, +117,116,118,105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 41, 59, 10,125, 10, 10,118,111,105,100, 32, +109, 97,116,104, 95, 97,100,100, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, + 97,108, 49, 32, 43, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,115,117, 98,116,114, 97, 99, +116, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108, +111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 45, 32,118, + 97,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109,117,108,116,105,112,108,121, 40,102,108,111, 97,116, + 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, +118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 42, 32,118, 97,108, 50, 59, 10,125, 10, + 10,118,111,105,100, 32,109, 97,116,104, 95,100,105,118,105,100,101, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108, +111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105, +102, 32, 40,118, 97,108, 50, 32, 61, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10, + 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 47, 32,118, 97,108, 50, 59, 10,125, 10, + 10,118,111,105,100, 32,109, 97,116,104, 95,115,105,110,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,115,105,110, 40,118, 97,108, + 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 99,111,115,105,110,101, 40,102,108,111, 97,116, 32,118, 97,108, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, + 99,111,115, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,116, 97,110,103,101,110,116, 40,102, +108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111, +117,116,118, 97,108, 32, 61, 32,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97, +115,105,110, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, + 10,123, 10, 9,105,102, 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, 49, 46, + 48, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 97,115,105,110, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, 10, 9, + 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97, 99,111,115, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, - 9,111,117,116,118, 97,108, 32, 61, 32,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, - 95, 97,115,105,110, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97, -108, 41, 10,123, 10, 9,105,102, 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, - 49, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 97,115,105,110, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, - 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97, 99, -111,115, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10, -123, 10, 9,105,102, 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, 49, 46, 48, - 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 97, 99,111,115, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, 10, 9, 9, -111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97,116, 97,110, 40, -102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9, -111,117,116,118, 97,108, 32, 61, 32, 97,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, - 95,112,111,119, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 32, 40,118, 97,108, 49, 32, 62, 61, 32, 48, 46, - 48, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32,112,111,119, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10, 9, -101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116, -104, 95,108,111,103, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117, -116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32, 48, 46, 48, - 32, 32, 38, 38, 32,118, 97,108, 50, 32, 62, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 61, 32,108,111,103, 50, 40, -118, 97,108, 49, 41, 32, 47, 32,108,111,103, 50, 40,118, 97,108, 50, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, - 97,108, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109, 97,120, 40,102,108,111, 97,116, 32, -118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, - 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, 97,120, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, - 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109,105,110, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108, -111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111, -117,116,118, 97,108, 32, 61, 32,109,105,110, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10,125, 10, 10,118,111,105,100, - 32,109, 97,116,104, 95,114,111,117,110,100, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, - 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 61, 32,102,108,111,111,114, 40,118, 97,108, 32, 43, 32, - 48, 46, 53, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,108,101,115,115, 95,116,104, 97,110, 40,102,108,111, - 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111, -117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 60, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, - 97,108, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10, -125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,103,114,101, 97,116,101,114, 95,116,104, 97,110, 40,102,108,111, 97,116, 32, -118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, - 97,108, 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, 97,108, 32, - 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10, -118,111,105,100, 32,115,113,117,101,101,122,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,102,108,111, 97,116, 32,119,105, -100,116,104, 44, 32,102,108,111, 97,116, 32, 99,101,110,116,101,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, -118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, 47, 40, 49, 46, 48, 32, 43, 32,112,111,119, 40, - 50, 46, 55, 49, 56, 50, 56, 49, 56, 51, 44, 32, 45, 40, 40,118, 97,108, 45, 99,101,110,116,101,114, 41, 42,119,105,100,116,104, - 41, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,100,100, 40,118,101, 99, 51, 32,118, - 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 43, 32, -118, 50, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, 32, - 97, 98,115, 40,111,117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, 41, - 47, 51, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,115,117, 98, 40,118,101, 99, 51, 32, -118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117, -116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 45, - 32,118, 50, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, - 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, - 41, 47, 51, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,118,101,114, 97,103,101, 40, -118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, - 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, - 32,118, 49, 32, 43, 32,118, 50, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, - 99, 41, 59, 10, 9,111,117,116,118,101, 99, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,118,101, 99, 41, 59, - 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,100,111,116, 40,118,101, 99, 51, 32,118, 49, 44, 32,118, -101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, - 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118,101, 99, 51, 40, 48, 44, 32, 48, - 44, 32, 48, 41, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32,100,111,116, 40,118, 49, 44, 32,118, 50, 41, 59, 10,125, 10, 10, -118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 99,114,111,115,115, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, + 9,105,102, 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, 49, 46, 48, 41, 10, + 9, 9,111,117,116,118, 97,108, 32, 61, 32, 97, 99,111,115, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117, +116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97,116, 97,110, 40,102,108, +111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117, +116,118, 97,108, 32, 61, 32, 97,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,112, +111,119, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 32, 40,118, 97,108, 49, 32, 62, 61, 32, 48, 46, 48, 41, + 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32,112,111,119, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10, 9,101,108, +115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, +108,111,103, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32, +102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32, 48, 46, 48, 32, 32, + 38, 38, 32,118, 97,108, 50, 32, 62, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 61, 32,108,111,103, 50, 40,118, 97, +108, 49, 41, 32, 47, 32,108,111,103, 50, 40,118, 97,108, 50, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, + 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109, 97,120, 40,102,108,111, 97,116, 32,118, 97, +108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, + 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, 97,120, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10,125, + 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109,105,110, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97, +116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116, +118, 97,108, 32, 61, 32,109,105,110, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, + 97,116,104, 95,114,111,117,110,100, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111, +117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 61, 32,102,108,111,111,114, 40,118, 97,108, 32, 43, 32, 48, 46, + 53, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,108,101,115,115, 95,116,104, 97,110, 40,102,108,111, 97,116, + 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, +118, 97,108, 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 60, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, 97,108, + 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, + 10,118,111,105,100, 32,109, 97,116,104, 95,103,114,101, 97,116,101,114, 95,116,104, 97,110, 40,102,108,111, 97,116, 32,118, 97, +108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, + 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, + 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111, +105,100, 32,115,113,117,101,101,122,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,102,108,111, 97,116, 32,119,105,100,116, +104, 44, 32,102,108,111, 97,116, 32, 99,101,110,116,101,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97, +108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, 47, 40, 49, 46, 48, 32, 43, 32,112,111,119, 40, 50, 46, + 55, 49, 56, 50, 56, 49, 56, 51, 44, 32, 45, 40, 40,118, 97,108, 45, 99,101,110,116,101,114, 41, 42,119,105,100,116,104, 41, 41, + 41, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,100,100, 40,118,101, 99, 51, 32,118, 49, 44, + 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 43, 32,118, 50, + 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, 32, 97, 98, +115, 40,111,117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, 41, 47, 51, + 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,115,117, 98, 40,118,101, 99, 51, 32,118, 49, + 44, 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32, +102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 45, 32,118, + 50, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, 32, 97, + 98,115, 40,111,117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, 41, 47, + 51, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,118,101,114, 97,103,101, 40,118,101, + 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, + 49, 32, 43, 32,118, 50, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, 99, 41, + 59, 10, 9,111,117,116,118,101, 99, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,118,101, 99, 41, 59, 10,125, + 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,100,111,116, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, - 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 99,114,111,115,115, 40,118, 49, 44, 32,118, - 50, 41, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, 99, 41, 59, 10,125, 10, - 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,110,111,114,109, 97,108,105,122,101, 40,118,101, 99, 51, 32,118, 44, - 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, - 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,118, 41, 59, 10, 9,111,117,116,118, -101, 99, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 41, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, - 97,116,104, 95,110,101,103, 97,116,101, 40,118,101, 99, 51, 32,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118, - 41, 10,123, 10, 9,111,117,116,118, 32, 61, 32, 45,118, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,114,109, 97,108, 40,118, -101, 99, 51, 32,100,105,114, 44, 32,118,101, 99, 51, 32,110,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110, -111,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,100,111,116, 41, 10,123, 10, 9,111,117,116,110,111,114, 32, - 61, 32,110,111,114, 59, 10, 9,111,117,116,100,111,116, 32, 61, 32, 45,100,111,116, 40,100,105,114, 44, 32,110,111,114, 41, 59, - 10,125, 10, 10,118,111,105,100, 32, 99,117,114,118,101,115, 95,118,101, 99, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118, -101, 99, 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, - 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 46,120, 32, 61, 32,116,101,120,116, -117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 40,118,101, 99, 46,120, 32, 43, 32, 49, 46, - 48, 41, 42, 48, 46, 53, 44, 32, 48, 46, 48, 41, 41, 46,120, 59, 10, 9,111,117,116,118,101, 99, 46,121, 32, 61, 32,116,101,120, -116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 40,118,101, 99, 46,121, 32, 43, 32, 49, - 46, 48, 41, 42, 48, 46, 53, 44, 32, 48, 46, 48, 41, 41, 46,121, 59, 10, 9,111,117,116,118,101, 99, 46,122, 32, 61, 32,116,101, -120,116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 40,118,101, 99, 46,122, 32, 43, 32, - 49, 46, 48, 41, 42, 48, 46, 53, 44, 32, 48, 46, 48, 41, 41, 46,122, 59, 10, 10, 9,105,102, 32, 40,102, 97, 99, 32, 33, 61, 32, - 49, 46, 48, 41, 10, 9, 9,111,117,116,118,101, 99, 32, 61, 32, 40,111,117,116,118,101, 99, 42,102, 97, 99, 41, 32, 43, 32, 40, -118,101, 99, 42, 40, 49, 46, 48, 45,102, 97, 99, 41, 41, 59, 10, 10,125, 10, 10,118,111,105,100, 32, 99,117,114,118,101,115, 95, -114,103, 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,115, 97,109,112,108,101,114, - 50, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, - 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, -118,101, 99, 50, 40,116,101,120,116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 99,111, -108, 46,114, 44, 32, 48, 46, 48, 41, 41, 46, 97, 44, 32, 48, 46, 48, 41, 41, 46,114, 59, 10, 9,111,117,116, 99,111,108, 46,103, - 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40,116,101,120,116, -117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 99,111,108, 46,103, 44, 32, 48, 46, 48, 41, - 41, 46, 97, 44, 32, 48, 46, 48, 41, 41, 46,103, 59, 10, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32,116,101,120,116,117,114, -101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40,116,101,120,116,117,114,101, 50, 68, 40, 99,117,114, -118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 99,111,108, 46, 98, 44, 32, 48, 46, 48, 41, 41, 46, 97, 44, 32, 48, 46, 48, 41, - 41, 46, 98, 59, 10, 10, 9,105,102, 32, 40,102, 97, 99, 32, 33, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 32, - 61, 32, 40,111,117,116, 99,111,108, 42,102, 97, 99, 41, 32, 43, 32, 40, 99,111,108, 42, 40, 49, 46, 48, 45,102, 97, 99, 41, 41, - 59, 10, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,115,101, -116, 95,118, 97,108,117,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, -118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,101, -116, 95,114,103, 98, 40,118,101, 99, 51, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, - 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, - 98, 97, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, - 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,118, 97,108,117,101, - 95,122,101,114,111, 40,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97, -108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,118, 97,108,117,101, 95,111,110,101, 40,111, -117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, - 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 95,122,101,114,111, 40,111,117,116, 32,118,101, 99, 51, 32, -111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 41, 59, 10,125, - 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 97, 95,122,101,114,111, 40,111,117,116, 32,118,101, 99, 52, 32,111,117, -116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 52, 40, 48, 46, 48, 41, 59, 10,125, 10, 10, -118,111,105,100, 32,109,105,120, 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99, -111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, - 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, - 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, - 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, - 97,100,100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99, -111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99, -108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109, -105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, - 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,109,117,108,116, + 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118,101, 99, 51, 40, 48, 44, 32, 48, 44, 32, + 48, 41, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32,100,111,116, 40,118, 49, 44, 32,118, 50, 41, 59, 10,125, 10, 10,118,111, +105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 99,114,111,115,115, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32, +118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111, +117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 99,114,111,115,115, 40,118, 49, 44, 32,118, 50, 41, + 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, 99, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,110,111,114,109, 97,108,105,122,101, 40,118,101, 99, 51, 32,118, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, + 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,118, 41, 59, 10, 9,111,117,116,118,101, 99, + 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 41, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116, +104, 95,110,101,103, 97,116,101, 40,118,101, 99, 51, 32,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118, 41, 10, +123, 10, 9,111,117,116,118, 32, 61, 32, 45,118, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,114,109, 97,108, 40,118,101, 99, + 51, 32,100,105,114, 44, 32,118,101, 99, 51, 32,110,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,100,111,116, 41, 10,123, 10, 9,111,117,116,110,111,114, 32, 61, 32, +110,111,114, 59, 10, 9,111,117,116,100,111,116, 32, 61, 32, 45,100,111,116, 40,100,105,114, 44, 32,110,111,114, 41, 59, 10,125, + 10, 10,118,111,105,100, 32, 99,117,114,118,101,115, 95,118,101, 99, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, + 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, 32,118, +101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 46,120, 32, 61, 32,116,101,120,116,117,114, +101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 40,118,101, 99, 46,120, 32, 43, 32, 49, 46, 48, 41, + 42, 48, 46, 53, 44, 32, 48, 46, 48, 41, 41, 46,120, 59, 10, 9,111,117,116,118,101, 99, 46,121, 32, 61, 32,116,101,120,116,117, +114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 40,118,101, 99, 46,121, 32, 43, 32, 49, 46, 48, + 41, 42, 48, 46, 53, 44, 32, 48, 46, 48, 41, 41, 46,121, 59, 10, 9,111,117,116,118,101, 99, 46,122, 32, 61, 32,116,101,120,116, +117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 40,118,101, 99, 46,122, 32, 43, 32, 49, 46, + 48, 41, 42, 48, 46, 53, 44, 32, 48, 46, 48, 41, 41, 46,122, 59, 10, 10, 9,105,102, 32, 40,102, 97, 99, 32, 33, 61, 32, 49, 46, + 48, 41, 10, 9, 9,111,117,116,118,101, 99, 32, 61, 32, 40,111,117,116,118,101, 99, 42,102, 97, 99, 41, 32, 43, 32, 40,118,101, + 99, 42, 40, 49, 46, 48, 45,102, 97, 99, 41, 41, 59, 10, 10,125, 10, 10,118,111,105,100, 32, 99,117,114,118,101,115, 95,114,103, + 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,115, 97,109,112,108,101,114, 50, 68, + 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111, +117,116, 99,111,108, 46,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, + 99, 50, 40,116,101,120,116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 99,111,108, 46, +114, 44, 32, 48, 46, 48, 41, 41, 46, 97, 44, 32, 48, 46, 48, 41, 41, 46,114, 59, 10, 9,111,117,116, 99,111,108, 46,103, 32, 61, + 32,116,101,120,116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40,116,101,120,116,117,114, +101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40, 99,111,108, 46,103, 44, 32, 48, 46, 48, 41, 41, 46, + 97, 44, 32, 48, 46, 48, 41, 41, 46,103, 59, 10, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32,116,101,120,116,117,114,101, 50, + 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40,116,101,120,116,117,114,101, 50, 68, 40, 99,117,114,118,101, +109, 97,112, 44, 32,118,101, 99, 50, 40, 99,111,108, 46, 98, 44, 32, 48, 46, 48, 41, 41, 46, 97, 44, 32, 48, 46, 48, 41, 41, 46, + 98, 59, 10, 10, 9,105,102, 32, 40,102, 97, 99, 32, 33, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32, + 40,111,117,116, 99,111,108, 42,102, 97, 99, 41, 32, 43, 32, 40, 99,111,108, 42, 40, 49, 46, 48, 45,102, 97, 99, 41, 41, 59, 10, + 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95, +118, 97,108,117,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97, +108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95, +114,103, 98, 40,118,101, 99, 51, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, + 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 97, + 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111, +117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,118, 97,108,117,101, 95,122, +101,114,111, 40,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, + 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,118, 97,108,117,101, 95,111,110,101, 40,111,117,116, + 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, 59, 10, +125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 95,122,101,114,111, 40,111,117,116, 32,118,101, 99, 51, 32,111,117, +116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 41, 59, 10,125, 10, 10, +118,111,105,100, 32,115,101,116, 95,114,103, 98, 97, 95,122,101,114,111, 40,111,117,116, 32,118,101, 99, 52, 32,111,117,116,118, + 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 52, 40, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111, +105,100, 32,109,105,120, 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, + 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, + 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111, +117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111, +117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 97,100, +100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, + 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97, +109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, + 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111, +108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,109,117,108,116, 40,102, +108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32, +111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40, +102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111, +108, 49, 44, 32, 99,111,108, 49, 32, 42, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, + 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, 99,114,101,101,110, 40,102,108, +111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111, +117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, + 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, + 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 49, 46, 48, 41, 32, 45, 32, 40, +118,101, 99, 52, 40,102, 97, 99,109, 41, 32, 43, 32,102, 97, 99, 42, 40,118,101, 99, 52, 40, 49, 46, 48, 41, 32, 45, 32, 99,111, +108, 50, 41, 41, 42, 40,118,101, 99, 52, 40, 49, 46, 48, 41, 32, 45, 32, 99,111,108, 49, 41, 59, 10, 9,111,117,116, 99,111,108, + 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,111,118,101,114,108, 97,121, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109, -112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, - 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 42, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, - 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, 99,114,101,101,110, 40, -102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, - 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, - 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, - 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 49, 46, 48, 41, 32, 45, - 32, 40,118,101, 99, 52, 40,102, 97, 99,109, 41, 32, 43, 32,102, 97, 99, 42, 40,118,101, 99, 52, 40, 49, 46, 48, 41, 32, 45, 32, - 99,111,108, 50, 41, 41, 42, 40,118,101, 99, 52, 40, 49, 46, 48, 41, 32, 45, 32, 99,111,108, 49, 41, 59, 10, 9,111,117,116, 99, -111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,111,118,101,114,108, - 97,121, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111, -108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, - 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, - 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9, -105,102, 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 42, 61, - 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,101,108,115,101, 10, 9, 9, -111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, - 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,114, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,114, - 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111,108, - 46,103, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46,103, 59, 10, 9,101,108, -115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, - 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,103, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, - 99,111,108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,111, -117,116, 99,111,108, 46, 98, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46, 98, - 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, - 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46, 98, 41, 41, 42, 40, 49, 46, 48, 32, - 45, 32,111,117,116, 99,111,108, 46, 98, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115,117, 98, 40,102,108,111, - 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117, -116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, - 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, - 44, 32, 99,111,108, 49, 32, 45, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, - 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,105,118, 40,102,108,111, 97,116, 32,102, - 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, - 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, - 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, - 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, 40, 99,111,108, 50, 46,114, 32, - 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,114, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,114, - 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,114, 47, 99,111,108, 50, 46,114, 59, 10, 9,105,102, 40, 99,111,108, 50, - 46,103, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,103, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111, -108, 46,103, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,103, 47, 99,111,108, 50, 46,103, 59, 10, 9,105,102, 40, 99, -111,108, 50, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46, 98, 32, 61, 32,102, 97, 99,109, 42,111,117, -116, 99,111,108, 46, 98, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46, 98, 47, 99,111,108, 50, 46, 98, 59, 10,125, 10, - 10,118,111,105,100, 32,109,105,120, 95,100,105,102,102, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99, -111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, - 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, - 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 97, 98,115, 40, 99,111,108, 49, 32, 45, 32, 99, -111,108, 50, 41, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, -125, 10, 10,118,111,105,100, 32,109,105,120, 95,100, 97,114,107, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, - 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, -108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, - 59, 10, 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109,105,110, 40, 99,111,108, 49, 46,114,103, 98, 44, 32, 99,111, -108, 50, 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, - 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,108,105,103,104,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, - 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, - 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, - 48, 41, 59, 10, 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109, 97,120, 40, 99,111,108, 49, 46,114,103, 98, 44, 32, - 99,111,108, 50, 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, - 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,111,100,103,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32, -118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111, -117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, - 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111, -108, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32, 49, 46, 48, 32, - 45, 32,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, - 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, - 32, 61, 32,111,117,116, 99,111,108, 46,114, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111, -108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, -116,109,112, 59, 10, 9,125, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, - 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, 50, 46,103, 59, 10, 9, - 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, - 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, 46,103, 47,116,109,112, - 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108, -115,101, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,109,112, 59, 10, 9,125, 10, 9,105,102, 40,111,117,116, - 99,111,108, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32, 49, 46, - 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, - 10, 9, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40, 40,116, -109,112, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, 9,111,117,116, - 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111,108, 46, 98, 32, - 61, 32,116,109,112, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 98,117,114,110, 40,102,108,111, 97,116, +112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, + 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, + 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 42, 61, 32,102, + 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117, +116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 40, + 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,114, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,114, 41, 59, + 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, + 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46,103, 59, 10, 9,101,108,115,101, + 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42, +102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,103, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111, +108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, + 99,111,108, 46, 98, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, + 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, + 32, 50, 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46, 98, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32, +111,117,116, 99,111,108, 46, 98, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115,117, 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32, 118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, - 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,116,109,112, 44, 32,102, 97, 99,109, 32, 61, 32, 49, - 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,116,109,112, - 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,105,102, 40,116,109,112, 32, 60, 61, - 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, - 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,114, 41, 47, -116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 48, 46, 48, 59, 10, 9, -101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, - 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,109,112, 59, 10, 10, 9,116, -109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,103, 59, 10, 9,105,102, 40,116,109,112, 32, - 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32, -105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,103, - 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 48, 46, 48, 59, - 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, - 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,109,112, 59, 10, 10, - 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, 9,105,102, 40,116,109, -112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115, -101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, - 46, 98, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 48, 46, - 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, - 98, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32,116,109,112, 59, - 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,104,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, + 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, + 99,111,108, 49, 32, 45, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99, +111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,105,118, 40,102,108,111, 97,116, 32,102, 97, 99, + 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, + 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, + 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, + 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, 40, 99,111,108, 50, 46,114, 32, 33, 61, + 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,114, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,114, 32, 43, + 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,114, 47, 99,111,108, 50, 46,114, 59, 10, 9,105,102, 40, 99,111,108, 50, 46,103, + 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,103, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46, +103, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,103, 47, 99,111,108, 50, 46,103, 59, 10, 9,105,102, 40, 99,111,108, + 50, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46, 98, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99, +111,108, 46, 98, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46, 98, 47, 99,111,108, 50, 46, 98, 59, 10,125, 10, 10,118, +111,105,100, 32,109,105,120, 95,100,105,102,102, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, + 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, + 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111, +117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 97, 98,115, 40, 99,111,108, 49, 32, 45, 32, 99,111,108, + 50, 41, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, + 10,118,111,105,100, 32,109,105,120, 95,100, 97,114,107, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99, +111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, + 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, + 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109,105,110, 40, 99,111,108, 49, 46,114,103, 98, 44, 32, 99,111,108, 50, + 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, + 10, 10,118,111,105,100, 32,109,105,120, 95,108,105,103,104,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, 108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, - 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, - 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 44, 32,116,109, -112, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9,105,102, - 40,104,115,118, 50, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40,111, -117,116, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, 50, 46,120, 59, 10, 9, - 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116,109,112, 41, 59, 32, 10, 10, 9, 9,111,117,116, 99,111, -108, 32, 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109,112, 44, 32,102, 97, 99, 41, 59, 10, 9, 9,111,117,116, - 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, - 97,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111, -108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, - 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, - 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9, -118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40,111,117,116, 99, -111,108, 44, 32,104,115,118, 41, 59, 10, 10, 9,105,102, 40,104,115,118, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, - 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9, 9,104,115,118, 46, -121, 32, 61, 32,102, 97, 99,109, 42,104,115,118, 46,121, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46,121, 59, 10, 9, 9,104, -115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10, 9,125, 10,125, 10, 10,118,111, -105,100, 32,109,105,120, 95,118, 97,108, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, - 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9, -102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, - 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, - 32,104,115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 49, 44, 32,104,115,118, 41, 59, 10, 9, -114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9,104,115,118, 46,122, 32, - 61, 32,102, 97, 99,109, 42,104,115,118, 46,122, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46,122, 59, 10, 9,104,115,118, 95, -116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, - 95, 99,111,108,111,114, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, - 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, - 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, - 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, - 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 44, 32,116,109,112, 59, 10, 9,114,103, 98, 95,116,111, - 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9,105,102, 40,104,115,118, 50, 46,121, 32, 33, 61, - 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40,111,117,116, 99,111,108, 44, 32,104,115,118, - 41, 59, 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, 50, 46,120, 59, 10, 9, 9,104,115,118, 46,121, 32, 61, 32,104, -115,118, 50, 46,121, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116,109,112, 41, 59, 32, 10, - 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109,112, 44, 32,102, 97, 99, - 41, 59, 10, 9, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, 10,125, 10, 10,118,111, -105,100, 32,109,105,120, 95,115,111,102,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, - 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, - 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108, -111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,118,101, 99, 52, 32,111,110,101, - 61, 32,118,101, 99, 52, 40, 49, 46, 48, 41, 59, 10, 9,118,101, 99, 52, 32,115, 99,114, 61, 32,111,110,101, 32, 45, 32, 40,111, -110,101, 32, 45, 32, 99,111,108, 50, 41, 42, 40,111,110,101, 32, 45, 32, 99,111,108, 49, 41, 59, 10, 9,111,117,116, 99,111,108, - 32, 61, 32,102, 97, 99,109, 42, 99,111,108, 49, 32, 43, 32,102, 97, 99, 42, 40, 40,111,110,101, 32, 45, 32, 99,111,108, 49, 41, - 42, 99,111,108, 50, 42, 99,111,108, 49, 32, 43, 32, 99,111,108, 49, 42,115, 99,114, 41, 59, 10,125, 10, 10,118,111,105,100, 32, -109,105,120, 95,108,105,110,101, 97,114, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, - 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9, -102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 10, 9,111,117, -116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, 40, 99,111,108, 50, 46,114, 32, 62, 32, 48, 46, 53, 41, 10, - 9, 9,111,117,116, 99,111,108, 46,114, 61, 32, 99,111,108, 49, 46,114, 32, 43, 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, 99, -111,108, 50, 46,114, 32, 45, 32, 48, 46, 53, 41, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 61, - 32, 99,111,108, 49, 46,114, 32, 43, 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, 99,111,108, 50, 46,114, 41, 32, 45, 32, 49, 46, - 48, 41, 59, 10, 10, 9,105,102, 40, 99,111,108, 50, 46,103, 32, 62, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46, -103, 61, 32, 99,111,108, 49, 46,103, 32, 43, 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, 99,111,108, 50, 46,103, 32, 45, 32, 48, - 46, 53, 41, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 61, 32, 99,111,108, 49, 46,103, 32, 43, - 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, 99,111,108, 50, 46,103, 41, 32, 45, 32, 49, 46, 48, 41, 59, 10, 10, 9,105,102, 40, - 99,111,108, 50, 46, 98, 32, 62, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 61, 32, 99,111,108, 49, 46, 98, - 32, 43, 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, 99,111,108, 50, 46, 98, 32, 45, 32, 48, 46, 53, 41, 41, 59, 10, 9,101,108, -115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 61, 32, 99,111,108, 49, 46, 98, 32, 43, 32,102, 97, 99, 42, 40, 50, 46, 48, - 42, 40, 99,111,108, 50, 46, 98, 41, 32, 45, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,118, 97,108,116,111,114, -103, 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32, 99,111,108,111,114,109, 97,112, - 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, - 97,108,112,104, 97, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40, 99,111,108, -111,114,109, 97,112, 44, 32,118,101, 99, 50, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 41, 59, 10, 9,111,117,116, 97,108,112,104, - 97, 32, 61, 32,111,117,116, 99,111,108, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,114,103, 98,116,111, 98,119, 40,118,101, - 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 32, 32, 10,123, 10, - 9,111,117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, 42, 48, 46, 51, 53, 32, 43, 32, 99,111,108,111,114, 46,103, - 42, 48, 46, 52, 53, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, 50, 59, 32, 47, 42, 32,107,101,101,112, 32,116,104,101, -115,101, 32,102, 97, 99,116,111,114,115, 32,105,110, 32,115,121,110, 99, 32,119,105,116,104, 32,116,101,120,116,117,114,101, 46, -104, 58, 82, 71, 66, 84, 79, 66, 87, 32, 42, 47, 10,125, 10, 10,118,111,105,100, 32,105,110,118,101,114,116, 40,102,108,111, 97, -116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, - 41, 10,123, 10, 9,111,117,116, 99,111,108, 46,120,121,122, 32, 61, 32,109,105,120, 40, 99,111,108, 46,120,121,122, 44, 32,118, -101, 99, 51, 40, 49, 46, 48, 44, 32, 49, 46, 48, 44, 32, 49, 46, 48, 41, 32, 45, 32, 99,111,108, 46,120,121,122, 44, 32,102, 97, - 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46,119, 32, 61, 32, 99,111,108, 46,119, 59, 10,125, 10, 10,118,111,105,100, 32,104, -117,101, 95,115, 97,116, 40,102,108,111, 97,116, 32,104,117,101, 44, 32,102,108,111, 97,116, 32,115, 97,116, 44, 32,102,108,111, - 97,116, 32,118, 97,108,117,101, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111, -117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32,104,115,118, 59, 10, 10, 9,114, -103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 10, 9,104,115,118, 91, 48, 93, 32, 43, 61, - 32, 40,104,117,101, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,105,102, 40,104,115,118, 91, 48, 93, 62, 49, 46, 48, 41, 32,104,115, -118, 91, 48, 93, 45, 61, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, 48, 93, 60, 48, 46, 48, 41, 32,104, -115,118, 91, 48, 93, 43, 61, 32, 49, 46, 48, 59, 10, 9,104,115,118, 91, 49, 93, 32, 42, 61, 32,115, 97,116, 59, 10, 9,105,102, - 40,104,115,118, 91, 49, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, 49, 46, 48, 59, 32,101,108,115,101, 32,105, -102, 40,104,115,118, 91, 49, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, 48, 46, 48, 59, 10, 9,104,115,118, 91, - 50, 93, 32, 42, 61, 32,118, 97,108,117,101, 59, 10, 9,105,102, 40,104,115,118, 91, 50, 93, 62, 49, 46, 48, 41, 32,104,115,118, - 91, 50, 93, 61, 32, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, 50, 93, 60, 48, 46, 48, 41, 32,104,115, -118, 91, 50, 93, 61, 32, 48, 46, 48, 59, 10, 10, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, - 99,111,108, 41, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 44, 32,111,117,116, 99,111,108, - 44, 32,102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,112, 97,114, 97,116,101, 95,114,103, 98, 40,118,101, 99, - 52, 32, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,103, 44, - 32,111,117,116, 32,102,108,111, 97,116, 32, 98, 41, 10,123, 10, 9,114, 32, 61, 32, 99,111,108, 46,114, 59, 10, 9,103, 32, 61, - 32, 99,111,108, 46,103, 59, 10, 9, 98, 32, 61, 32, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105,100, 32, 99,111,109, 98, -105,110,101, 95,114,103, 98, 40,102,108,111, 97,116, 32,114, 44, 32,102,108,111, 97,116, 32,103, 44, 32,102,108,111, 97,116, 32, - 98, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108, 41, 10,123, 10, 9, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,114, - 44, 32,103, 44, 32, 98, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,111,117,116,112,117,116, 95,110,111,100, -101, 40,118,101, 99, 52, 32,114,103, 98, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 44, 32,111,117,116, 32,118,101, 99, - 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,114,103, 98, 46,114, -103, 98, 44, 32, 97,108,112,104, 97, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 84, 69, 88, 84, - 85, 82, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, 32,116,101,120,116, -117,114,101, 95,102,108,105,112, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,118,101, 99, - 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118,101, 99, 46,121,120,122, 59, 10,125, - 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95, 98,108,101,110,100, 95,108,105,110, 40,118,101, 99, 51, 32,118,101, - 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, - 32, 40, 49, 46, 48, 43,118,101, 99, 46,120, 41, 47, 50, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114, -101, 95, 98,108,101,110,100, 95,113,117, 97,100, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, - 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, 97,120, 40, 40, 49, 46, 48, 43,118,101, - 99, 46,120, 41, 47, 50, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10, 9,111,117,116,118, 97,108, 32, 42, 61, 32,111,117,116,118, 97, -108, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,119,111,111,100, 95,115,105,110, 40,118,101, 99, 51, - 32,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, - 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 41, 10,123, 10, 9,102,108,111, 97,116, - 32, 97, 32, 61, 32,115,113,114,116, 40,118,101, 99, 46,120, 42,118,101, 99, 46,120, 32, 43, 32,118,101, 99, 46,121, 42,118,101, - 99, 46,121, 32, 43, 32,118,101, 99, 46,122, 42,118,101, 99, 46,122, 41, 42, 50, 48, 46, 48, 59, 10, 9,102,108,111, 97,116, 32, -119,105, 32, 61, 32, 48, 46, 53, 32, 43, 32, 48, 46, 53, 42,115,105,110, 40, 97, 41, 59, 10, 10, 9,118, 97,108,117,101, 32, 61, - 32,119,105, 59, 10, 9, 99,111,108,111,114, 32, 61, 32,118,101, 99, 52, 40,119,105, 44, 32,119,105, 44, 32,119,105, 44, 32, 49, - 46, 48, 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, - 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,105,109, 97,103,101, 40,118,101, 99, 51, 32,118, -101, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 97,108, -117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114, -109, 97,108, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 40, -118,101, 99, 46,120,121, 32, 43, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, 41, 42, 48, 46, 53, 41, 59, 10, 9, -118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 59, 10, 10, 9,110,111,114,109, 97,108, 46,120, 32, 61, 32, 50, 46, 48, 42, 40, 99, -111,108,111,114, 46,114, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,110,111,114,109, 97,108, 46,121, 32, 61, 32, 50, 46, 48, 42, 40, - 48, 46, 53, 32, 45, 32, 99,111,108,111,114, 46,103, 41, 59, 10, 9,110,111,114,109, 97,108, 46,122, 32, 61, 32, 50, 46, 48, 42, - 40, 99,111,108,111,114, 46, 98, 32, 45, 32, 48, 46, 53, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 32, 77, 84, 69, 88, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, - 32,116,101,120, 99,111, 95,111,114, 99,111, 40,118,101, 99, 51, 32, 97,116,116,111,114, 99,111, 44, 32,111,117,116, 32,118,101, - 99, 51, 32,111,114, 99,111, 41, 10,123, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116,111,114, 99,111, 59, 10,125, 10, 10,118, -111,105,100, 32,116,101,120, 99,111, 95,117,118, 40,118,101, 99, 50, 32, 97,116,116,117,118, 44, 32,111,117,116, 32,118,101, 99, - 51, 32,117,118, 41, 10,123, 10, 9, 47, 42, 32,100,105,115, 97, 98,108,101,100, 32,102,111,114, 32,110,111,119, 44, 32,119,111, -114,107,115, 32,116,111,103,101,116,104,101,114, 32,119,105,116,104, 32,108,101, 97,118,105,110,103, 32,111,117,116, 32,109,116, -101,120, 95, 50,100, 95,109, 97,112,112,105,110,103, 10, 9, 32, 32, 32,117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117, -118, 42, 50, 46, 48, 32, 45, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, 44, 32, 48, 46, 48, 41, 59, 32, 42, 47, - 10, 9,117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, - 32,116,101,120, 99,111, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, - 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 99,111,114,114,101,115,112,111,110,100,115, 32,116, -111, 32,115,104,105, 45, 62,111,114,110, 44, 32,119,104,105, 99,104, 32,105,115, 32,110,101,103, 97,116,101,100, 32,115,111, 32, - 99, 97,110, 99,101,108,115, 10, 9, 32, 32, 32,111,117,116, 32, 98,108,101,110,100,101,114, 32,110,111,114,109, 97,108, 32,110, -101,103, 97,116,105,111,110, 32, 42, 47, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32,110,111,114,109, 97,108,105,122, -101, 40,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,116, 97,110,103,101,110,116, - 40,118,101, 99, 52, 32,116, 97,110,103,101,110,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,116, 97,110,103,101, -110,116, 41, 10,123, 10, 9,111,117,116,116, 97,110,103,101,110,116, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,116, 97, -110,103,101,110,116, 46,120,121,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,103,108,111, 98, 97,108, - 40,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118, -101, 99, 51, 32,103,108,111, 98, 97,108, 41, 10,123, 10, 9,103,108,111, 98, 97,108, 32, 61, 32, 40,118,105,101,119,105,110,118, -109, 97,116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10,125, 10, 10,118,111,105,100, 32, -116,101,120, 99,111, 95,111, 98,106,101, 99,116, 40,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,109, 97, -116, 52, 32,111, 98,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111, - 98,106,101, 99,116, 41, 10,123, 10, 9,111, 98,106,101, 99,116, 32, 61, 32, 40,111, 98,105,110,118,109, 97,116, 42, 40,118,105, -101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 41, 46,120,121,122, 59, 10,125, 10, - 10,118,111,105,100, 32,116,101,120, 99,111, 95,114,101,102,108, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, 32,118, -105,101,119, 44, 32,111,117,116, 32,118,101, 99, 51, 32,114,101,102, 41, 10,123, 10, 9,114,101,102, 32, 61, 32,118,105,101,119, - 32, 45, 32, 50, 46, 48, 42,100,111,116, 40,118,110, 44, 32,118,105,101,119, 41, 42,118,110, 59, 10,125, 10, 10,118,111,105,100, - 32,115,104, 97,100,101, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, - 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 98,108,101,110,100,101,114, 32,114,101,110,100,101, -114, 32,110,111,114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9,111,117,116,110,111,114,109, 97, -108, 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32, -109,116,101,120, 95,114,103, 98, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, - 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, - 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, - 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, - 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,102, 97, 99,109, 42,111, -117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,109,117,108, 40,118,101, 99, 51, - 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, - 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, - 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, - 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,103, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32, 40,102, 97, 99,109, 32, 43, - 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95,114,103, 98, 95,115, 99,114,101,101,110, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32, -116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32, -111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, - 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,103, 59, - 10, 10, 9,105,110, 99,111,108, 32, 61, 32,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32, 40,118,101, 99, 51, 40,102, 97, 99, -109, 41, 32, 43, 32,102, 97, 99,116, 42, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,116,101,120, 99,111,108, 41, 41, 42, - 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95,114,103, 98, 95,111,118,101,114,108, 97,121, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, - 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, - 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, - 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,103, - 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105,110, 99,111,108, 46,114, - 32, 61, 32,111,117,116, 99,111,108, 46,114, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, - 99,111,108, 46,114, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 32, 45, 32, - 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 46,114, - 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,114, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, - 46,103, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105,110, 99,111,108, 46,103, 32, 61, 32,111,117,116, 99,111,108, 46,103, 42, 40, -102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,103, 41, 59, 10, 9,101,108,115,101, - 10, 9, 9,105,110, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, - 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 46,103, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, - 99,111,108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105, -110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, - 99,116, 42,116,101,120, 99,111,108, 46, 98, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46, 98, 32, 61, 32, - 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101, -120, 99,111,108, 46, 98, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46, 98, 41, 59, 10,125, 10, 10,118,111, -105,100, 32,109,116,101,120, 95,114,103, 98, 95,115,117, 98, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, - 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, - 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, 32, 61, 32, 45,102, 97, - 99,116, 42,102, 97, 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, - 32,109,116,101,120, 95,114,103, 98, 95, 97,100,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32, -116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32, -111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42, -102, 97, 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95,114,103, 98, 95,100,105,118, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, - 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, - 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, 97, - 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9, -105,102, 40,116,101,120, 99,111,108, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32,102, 97, - 99,109, 42,111,117,116, 99,111,108, 46,114, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 46,114, 47,116,101,120, 99, -111,108, 46,114, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, - 46,103, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,103, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, - 46,103, 47,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46, 98, 32, 33, 61, 32, 48, 46, 48, - 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46, 98, 32, 43, 32,102, 97, 99,116, - 42,111,117,116, 99,111,108, 46, 98, 47,116,101,120, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, - 95,114,103, 98, 95,100,105,102,102, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99, -111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32, -118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, 97, 99, -116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9,105, -110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, 97, 98,115, 40,116,101, -120, 99,111,108, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, - 95,100, 97,114,107, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32, -102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, - 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32, 99,111,108, 59, 10, 10, 9,102, 97, - 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9, - 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111, -117,116, 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99, -111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, - 99,111,108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 46,103, 41, 32,105,110, 99,111,108, - 46,103, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,103, 32, 61, 32,111,117,116, 99,111,108, 46, -103, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 59, 10, 9,105,102, 40, 99,111,108, - 32, 60, 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, - 32,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101, -120, 95,114,103, 98, 95,108,105,103,104,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101, + 59, 10, 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109, 97,120, 40, 99,111,108, 49, 46,114,103, 98, 44, 32, 99,111, +108, 50, 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, + 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,111,100,103,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, + 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, + 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, + 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, +114, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32, 49, 46, 48, 32, 45, 32, +102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9, 9, +111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, + 32,111,117,116, 99,111,108, 46,114, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46, +114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,109, +112, 59, 10, 9,125, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102, +108,111, 97,116, 32,116,109,112, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, 50, 46,103, 59, 10, 9, 9,105, +102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 59, + 10, 9, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, 46,103, 47,116,109,112, 41, 32, + 62, 32, 49, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, + 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,109,112, 59, 10, 9,125, 10, 9,105,102, 40,111,117,116, 99,111, +108, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32, 49, 46, 48, 32, + 45, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, + 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, + 32, 61, 32,111,117,116, 99,111,108, 46, 98, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111, +108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, +116,109,112, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 98,117,114,110, 40,102,108,111, 97,116, 32,102, + 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, + 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, + 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,116,109,112, 44, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, + 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,116,109,112, 32, 61, + 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, + 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40, 40, +116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,114, 41, 47,116,109, +112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108, +115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, + 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,109,112, 59, 10, 10, 9,116,109,112, + 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,103, 59, 10, 9,105,102, 40,116,109,112, 32, 60, 61, + 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, + 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,103, 41, 47, +116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 48, 46, 48, 59, 10, 9, +101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, + 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,109,112, 59, 10, 10, 9,116, +109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, 9,105,102, 40,116,109,112, 32, + 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32, +105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46, 98, + 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 48, 46, 48, 59, + 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, + 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32,116,109,112, 59, 10,125, + 10, 10,118,111,105,100, 32,109,105,120, 95,104,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99, +111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, + 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, + 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111, +108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 44, 32,116,109,112, 59, + 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9,105,102, 40,104, +115,118, 50, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40,111,117,116, + 99,111,108, 44, 32,104,115,118, 41, 59, 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, 50, 46,120, 59, 10, 9, 9,104, +115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116,109,112, 41, 59, 32, 10, 10, 9, 9,111,117,116, 99,111,108, 32, + 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109,112, 44, 32,102, 97, 99, 41, 59, 10, 9, 9,111,117,116, 99,111, +108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, 97,116, + 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109, +112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, + 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,118,101, + 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40,111,117,116, 99,111,108, + 44, 32,104,115,118, 41, 59, 10, 10, 9,105,102, 40,104,115,118, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114, +103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9, 9,104,115,118, 46,121, 32, + 61, 32,102, 97, 99,109, 42,104,115,118, 46,121, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46,121, 59, 10, 9, 9,104,115,118, + 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, + 32,109,105,120, 95,118, 97,108, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118, +101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, + 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104, +115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 49, 44, 32,104,115,118, 41, 59, 10, 9,114,103, + 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9,104,115,118, 46,122, 32, 61, 32, +102, 97, 99,109, 42,104,115,118, 46,122, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46,122, 59, 10, 9,104,115,118, 95,116,111, + 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 99, +111,108,111,114, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, + 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, + 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99, +109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, + 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 44, 32,116,109,112, 59, 10, 9,114,103, 98, 95,116,111, 95,104, +115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9,105,102, 40,104,115,118, 50, 46,121, 32, 33, 61, 32, 48, + 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40,111,117,116, 99,111,108, 44, 32,104,115,118, 41, 59, + 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, 50, 46,120, 59, 10, 9, 9,104,115,118, 46,121, 32, 61, 32,104,115,118, + 50, 46,121, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116,109,112, 41, 59, 32, 10, 10, 9, + 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109,112, 44, 32,102, 97, 99, 41, 59, + 10, 9, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, + 32,109,105,120, 95,115,111,102,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32, +118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, + 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97, +116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,118,101, 99, 52, 32,111,110,101, 61, 32, +118,101, 99, 52, 40, 49, 46, 48, 41, 59, 10, 9,118,101, 99, 52, 32,115, 99,114, 61, 32,111,110,101, 32, 45, 32, 40,111,110,101, + 32, 45, 32, 99,111,108, 50, 41, 42, 40,111,110,101, 32, 45, 32, 99,111,108, 49, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, + 32,102, 97, 99,109, 42, 99,111,108, 49, 32, 43, 32,102, 97, 99, 42, 40, 40,111,110,101, 32, 45, 32, 99,111,108, 49, 41, 42, 99, +111,108, 50, 42, 99,111,108, 49, 32, 43, 32, 99,111,108, 49, 42,115, 99,114, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105, +120, 95,108,105,110,101, 97,114, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118, +101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, + 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 10, 9,111,117,116, 99, +111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, 40, 99,111,108, 50, 46,114, 32, 62, 32, 48, 46, 53, 41, 10, 9, 9, +111,117,116, 99,111,108, 46,114, 61, 32, 99,111,108, 49, 46,114, 32, 43, 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, 99,111,108, + 50, 46,114, 32, 45, 32, 48, 46, 53, 41, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 61, 32, 99, +111,108, 49, 46,114, 32, 43, 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, 99,111,108, 50, 46,114, 41, 32, 45, 32, 49, 46, 48, 41, + 59, 10, 10, 9,105,102, 40, 99,111,108, 50, 46,103, 32, 62, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 61, + 32, 99,111,108, 49, 46,103, 32, 43, 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, 99,111,108, 50, 46,103, 32, 45, 32, 48, 46, 53, + 41, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 61, 32, 99,111,108, 49, 46,103, 32, 43, 32,102, + 97, 99, 42, 40, 50, 46, 48, 42, 40, 99,111,108, 50, 46,103, 41, 32, 45, 32, 49, 46, 48, 41, 59, 10, 10, 9,105,102, 40, 99,111, +108, 50, 46, 98, 32, 62, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 61, 32, 99,111,108, 49, 46, 98, 32, 43, + 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, 99,111,108, 50, 46, 98, 32, 45, 32, 48, 46, 53, 41, 41, 59, 10, 9,101,108,115,101, + 10, 9, 9,111,117,116, 99,111,108, 46, 98, 61, 32, 99,111,108, 49, 46, 98, 32, 43, 32,102, 97, 99, 42, 40, 50, 46, 48, 42, 40, + 99,111,108, 50, 46, 98, 41, 32, 45, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,118, 97,108,116,111,114,103, 98, + 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32, 99,111,108,111,114,109, 97,112, 44, 32, +111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, 97,108, +112,104, 97, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40, 99,111,108,111,114, +109, 97,112, 44, 32,118,101, 99, 50, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 41, 59, 10, 9,111,117,116, 97,108,112,104, 97, 32, + 61, 32,111,117,116, 99,111,108, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,114,103, 98,116,111, 98,119, 40,118,101, 99, 52, + 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 32, 32, 10,123, 10, 9,111, +117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, 42, 48, 46, 51, 53, 32, 43, 32, 99,111,108,111,114, 46,103, 42, 48, + 46, 52, 53, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, 50, 59, 32, 47, 42, 32,107,101,101,112, 32,116,104,101,115,101, + 32,102, 97, 99,116,111,114,115, 32,105,110, 32,115,121,110, 99, 32,119,105,116,104, 32,116,101,120,116,117,114,101, 46,104, 58, + 82, 71, 66, 84, 79, 66, 87, 32, 42, 47, 10,125, 10, 10,118,111,105,100, 32,105,110,118,101,114,116, 40,102,108,111, 97,116, 32, +102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10, +123, 10, 9,111,117,116, 99,111,108, 46,120,121,122, 32, 61, 32,109,105,120, 40, 99,111,108, 46,120,121,122, 44, 32,118,101, 99, + 51, 40, 49, 46, 48, 44, 32, 49, 46, 48, 44, 32, 49, 46, 48, 41, 32, 45, 32, 99,111,108, 46,120,121,122, 44, 32,102, 97, 99, 41, + 59, 10, 9,111,117,116, 99,111,108, 46,119, 32, 61, 32, 99,111,108, 46,119, 59, 10,125, 10, 10,118,111,105,100, 32,104,117,101, + 95,115, 97,116, 40,102,108,111, 97,116, 32,104,117,101, 44, 32,102,108,111, 97,116, 32,115, 97,116, 44, 32,102,108,111, 97,116, + 32,118, 97,108,117,101, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, + 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32,104,115,118, 59, 10, 10, 9,114,103, 98, + 95,116,111, 95,104,115,118, 40, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 10, 9,104,115,118, 91, 48, 93, 32, 43, 61, 32, 40, +104,117,101, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,105,102, 40,104,115,118, 91, 48, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, + 48, 93, 45, 61, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, 48, 93, 60, 48, 46, 48, 41, 32,104,115,118, + 91, 48, 93, 43, 61, 32, 49, 46, 48, 59, 10, 9,104,115,118, 91, 49, 93, 32, 42, 61, 32,115, 97,116, 59, 10, 9,105,102, 40,104, +115,118, 91, 49, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40, +104,115,118, 91, 49, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, 48, 46, 48, 59, 10, 9,104,115,118, 91, 50, 93, + 32, 42, 61, 32,118, 97,108,117,101, 59, 10, 9,105,102, 40,104,115,118, 91, 50, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 50, + 93, 61, 32, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, 50, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, + 50, 93, 61, 32, 48, 46, 48, 59, 10, 10, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111, +108, 41, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 44, 32,111,117,116, 99,111,108, 44, 32, +102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,112, 97,114, 97,116,101, 95,114,103, 98, 40,118,101, 99, 52, 32, + 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,103, 44, 32,111, +117,116, 32,102,108,111, 97,116, 32, 98, 41, 10,123, 10, 9,114, 32, 61, 32, 99,111,108, 46,114, 59, 10, 9,103, 32, 61, 32, 99, +111,108, 46,103, 59, 10, 9, 98, 32, 61, 32, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105,100, 32, 99,111,109, 98,105,110, +101, 95,114,103, 98, 40,102,108,111, 97,116, 32,114, 44, 32,102,108,111, 97,116, 32,103, 44, 32,102,108,111, 97,116, 32, 98, 44, + 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108, 41, 10,123, 10, 9, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,114, 44, 32, +103, 44, 32, 98, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,111,117,116,112,117,116, 95,110,111,100,101, 40, +118,101, 99, 52, 32,114,103, 98, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 44, 32,111,117,116, 32,118,101, 99, 52, 32, +111,117,116,114,103, 98, 41, 10,123, 10, 9,111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,114,103, 98, 46,114,103, 98, + 44, 32, 97,108,112,104, 97, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 84, 69, 88, 84, 85, 82, + 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, 32,116,101,120,116,117,114, +101, 95,102,108,105,112, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32, +111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118,101, 99, 46,121,120,122, 59, 10,125, 10, 10, +118,111,105,100, 32,116,101,120,116,117,114,101, 95, 98,108,101,110,100, 95,108,105,110, 40,118,101, 99, 51, 32,118,101, 99, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 40, + 49, 46, 48, 43,118,101, 99, 46,120, 41, 47, 50, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95, + 98,108,101,110,100, 95,113,117, 97,100, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111, +117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, 97,120, 40, 40, 49, 46, 48, 43,118,101, 99, 46, +120, 41, 47, 50, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10, 9,111,117,116,118, 97,108, 32, 42, 61, 32,111,117,116,118, 97,108, 59, + 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,119,111,111,100, 95,115,105,110, 40,118,101, 99, 51, 32,118, +101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111, +108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, 97, + 32, 61, 32,115,113,114,116, 40,118,101, 99, 46,120, 42,118,101, 99, 46,120, 32, 43, 32,118,101, 99, 46,121, 42,118,101, 99, 46, +121, 32, 43, 32,118,101, 99, 46,122, 42,118,101, 99, 46,122, 41, 42, 50, 48, 46, 48, 59, 10, 9,102,108,111, 97,116, 32,119,105, + 32, 61, 32, 48, 46, 53, 32, 43, 32, 48, 46, 53, 42,115,105,110, 40, 97, 41, 59, 10, 10, 9,118, 97,108,117,101, 32, 61, 32,119, +105, 59, 10, 9, 99,111,108,111,114, 32, 61, 32,118,101, 99, 52, 40,119,105, 44, 32,119,105, 44, 32,119,105, 44, 32, 49, 46, 48, + 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, + 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,105,109, 97,103,101, 40,118,101, 99, 51, 32,118,101, 99, + 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 97,108,117,101, + 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97, +108, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 40,118,101, + 99, 46,120,121, 32, 43, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, 41, 42, 48, 46, 53, 41, 59, 10, 9,118, 97, +108,117,101, 32, 61, 32, 49, 46, 48, 59, 10, 10, 9,110,111,114,109, 97,108, 46,120, 32, 61, 32, 50, 46, 48, 42, 40, 99,111,108, +111,114, 46,114, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,110,111,114,109, 97,108, 46,121, 32, 61, 32, 50, 46, 48, 42, 40, 48, 46, + 53, 32, 45, 32, 99,111,108,111,114, 46,103, 41, 59, 10, 9,110,111,114,109, 97,108, 46,122, 32, 61, 32, 50, 46, 48, 42, 40, 99, +111,108,111,114, 46, 98, 32, 45, 32, 48, 46, 53, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 32, 77, 84, 69, 88, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, 32,116, +101,120, 99,111, 95,111,114, 99,111, 40,118,101, 99, 51, 32, 97,116,116,111,114, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, + 32,111,114, 99,111, 41, 10,123, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116,111,114, 99,111, 59, 10,125, 10, 10,118,111,105, +100, 32,116,101,120, 99,111, 95,117,118, 40,118,101, 99, 50, 32, 97,116,116,117,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32, +117,118, 41, 10,123, 10, 9, 47, 42, 32,100,105,115, 97, 98,108,101,100, 32,102,111,114, 32,110,111,119, 44, 32,119,111,114,107, +115, 32,116,111,103,101,116,104,101,114, 32,119,105,116,104, 32,108,101, 97,118,105,110,103, 32,111,117,116, 32,109,116,101,120, + 95, 50,100, 95,109, 97,112,112,105,110,103, 10, 9, 32, 32, 32,117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 42, + 50, 46, 48, 32, 45, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, 44, 32, 48, 46, 48, 41, 59, 32, 42, 47, 10, 9, +117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116, +101,120, 99,111, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32, +111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 99,111,114,114,101,115,112,111,110,100,115, 32,116,111, 32, +115,104,105, 45, 62,111,114,110, 44, 32,119,104,105, 99,104, 32,105,115, 32,110,101,103, 97,116,101,100, 32,115,111, 32, 99, 97, +110, 99,101,108,115, 10, 9, 32, 32, 32,111,117,116, 32, 98,108,101,110,100,101,114, 32,110,111,114,109, 97,108, 32,110,101,103, + 97,116,105,111,110, 32, 42, 47, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, +110,111,114,109, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,116, 97,110,103,101,110,116, 40,118, +101, 99, 52, 32,116, 97,110,103,101,110,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,116, 97,110,103,101,110,116, + 41, 10,123, 10, 9,111,117,116,116, 97,110,103,101,110,116, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,116, 97,110,103, +101,110,116, 46,120,121,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,103,108,111, 98, 97,108, 40,109, + 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, + 51, 32,103,108,111, 98, 97,108, 41, 10,123, 10, 9,103,108,111, 98, 97,108, 32, 61, 32, 40,118,105,101,119,105,110,118,109, 97, +116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10,125, 10, 10,118,111,105,100, 32,116,101, +120, 99,111, 95,111, 98,106,101, 99,116, 40,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,109, 97,116, 52, + 32,111, 98,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111, 98,106, +101, 99,116, 41, 10,123, 10, 9,111, 98,106,101, 99,116, 32, 61, 32, 40,111, 98,105,110,118,109, 97,116, 42, 40,118,105,101,119, +105,110,118,109, 97,116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 41, 46,120,121,122, 59, 10,125, 10, 10,118, +111,105,100, 32,116,101,120, 99,111, 95,114,101,102,108, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, 32,118,105,101, +119, 44, 32,111,117,116, 32,118,101, 99, 51, 32,114,101,102, 41, 10,123, 10, 9,114,101,102, 32, 61, 32,118,105,101,119, 32, 45, + 32, 50, 46, 48, 42,100,111,116, 40,118,110, 44, 32,118,105,101,119, 41, 42,118,110, 59, 10,125, 10, 10,118,111,105,100, 32,115, +104, 97,100,101, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32, +111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 98,108,101,110,100,101,114, 32,114,101,110,100,101,114, 32, +110,111,114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9,111,117,116,110,111,114,109, 97,108, 32, + 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, +101,120, 95,114,103, 98, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116, +101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9, +102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, 59, 10, + 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,102, 97, 99,109, 42,111,117,116, + 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,109,117,108, 40,118,101, 99, 51, 32,111, +117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32, +102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102, +108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, + 32, 61, 32, 49, 46, 48, 45,102, 97, 99,103, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32, 40,102, 97, 99,109, 32, 43, 32,102, + 97, 99,116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95,114,103, 98, 95,115, 99,114,101,101,110, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101, 120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117, -116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32, 99,111,108, - 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, - 99,116, 59, 10, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40, 99, -111,108, 32, 62, 32,111,117,116, 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99,111,108, 59, 32,101,108, -115,101, 32,105,110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, - 99,116, 42,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46,103, 41, - 32,105,110, 99,111,108, 46,103, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,103, 32, 61, 32,111, -117,116, 99,111,108, 46,103, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 59, 10, 9, -105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32, 99,111,108, - 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111, -105,100, 32,109,116,101,120, 95,114,103, 98, 95,104,117,101, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, - 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, - 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, - 9,109,105,120, 95,104,117,101, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, - 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, - 9,105,110, 99,111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95,114,103, 98, 95,115, 97,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, - 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, - 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, 95, -115, 97,116, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, 41, - 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99,111, -108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, - 98, 95,118, 97,108, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32, -102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, - 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, 95,118, 97,108, 40,102, - 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, - 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99,111,108, 46,114,103, 98, - 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95, 99,111,108, -111,114, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, - 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, - 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, 95, 99,111,108,111,114, 40,102, 97, - 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, - 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99,111,108, 46,114,103, 98, 32, - 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97, -114,115, 40,105,110,111,117,116, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, - 32,111,117,116, 32,102,108,111, 97,116, 32,102, 97, 99,109, 41, 10,123, 10, 9,102, 97, 99,116, 32, 42, 61, 32, 97, 98,115, 40, -102, 97, 99,103, 41, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9,105,102, 40,102, 97, - 99,103, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32,102, 97, 99,116, 59, 10, - 9, 9,102, 97, 99,116, 32, 61, 32,102, 97, 99,109, 59, 10, 9, 9,102, 97, 99,109, 32, 61, 32,116,109,112, 59, 10, 9,125, 10, -125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,111, -117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, - 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, - 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, - 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42, -116,101,120, 99,111,108, 32, 43, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95,118, 97,108,117,101, 95,109,117,108, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, - 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, - 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, - 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, - 99,109, 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99,103, 59, 10, 9,105,110, 99,111,108, - 32, 61, 32, 40,102, 97, 99,109, 32, 43, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10, -125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,115, 99,114,101,101,110, 40,102,108,111, 97,116, 32, -111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, - 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, - 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, - 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, - 32,102, 97, 99,103, 59, 10, 9,105,110, 99,111,108, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32,102, 97, - 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, - 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,115,117, 98, 40,102,108,111, 97,116, 32, -111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, - 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, - 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, - 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, 32, 45,102, 97, 99,116, - 59, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, - 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95, 97,100,100, 40,102,108,111, 97,116, 32,111,117, +116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, + 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,103, 59, 10, 10, + 9,105,110, 99,111,108, 32, 61, 32,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32, 40,118,101, 99, 51, 40,102, 97, 99,109, 41, + 32, 43, 32,102, 97, 99,116, 42, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,116,101,120, 99,111,108, 41, 41, 42, 40,118, +101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95,114,103, 98, 95,111,118,101,114,108, 97,121, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116, +101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9, +102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,103, 59, 10, + 10, 9,105,102, 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105,110, 99,111,108, 46,114, 32, 61, + 32,111,117,116, 99,111,108, 46,114, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, 99,111, +108, 46,114, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, + 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 46,114, 41, 41, + 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,114, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, + 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105,110, 99,111,108, 46,103, 32, 61, 32,111,117,116, 99,111,108, 46,103, 42, 40,102, 97, + 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,103, 41, 59, 10, 9,101,108,115,101, 10, 9, + 9,105,110, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, +116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 46,103, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111, +108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105,110, 99, +111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, + 42,116,101,120, 99,111,108, 46, 98, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46, 98, 32, 61, 32, 49, 46, + 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99, +111,108, 46, 98, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46, 98, 41, 59, 10,125, 10, 10,118,111,105,100, + 32,109,116,101,120, 95,114,103, 98, 95,115,117, 98, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32, +116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32, +111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, 32, 61, 32, 45,102, 97, 99,116, + 42,102, 97, 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109, +116,101,120, 95,114,103, 98, 95, 97,100,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101, +120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117, +116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,102, 97, + 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95,114,103, 98, 95,100,105,118, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111, +108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118, +101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, + 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9,105,102, + 40,116,101,120, 99,111,108, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32,102, 97, 99,109, + 42,111,117,116, 99,111,108, 46,114, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 46,114, 47,116,101,120, 99,111,108, + 46,114, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, 46,103, + 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,103, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 46,103, + 47,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32, +105,110, 99,111,108, 46, 98, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46, 98, 32, 43, 32,102, 97, 99,116, 42,111, +117,116, 99,111,108, 46, 98, 47,116,101,120, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114, +103, 98, 95,100,105,102,102, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, + 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, + 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, + 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9,105,110, 99, +111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, 97, 98,115, 40,116,101,120, 99, +111,108, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,100, + 97,114,107, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108, +111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105, +110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32, 99,111,108, 59, 10, 10, 9,102, 97, 99,116, + 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9, 99,111, +108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, + 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, + 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111, +108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 46,103, 41, 32,105,110, 99,111,108, 46,103, + 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,103, 32, 61, 32,111,117,116, 99,111,108, 46,103, 59, + 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, + 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105, +110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, +114,103, 98, 95,108,105,103,104,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99, +111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32, +118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32, 99,111,108, 59, 10, + 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, + 59, 10, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40, 99,111,108, + 32, 62, 32,111,117,116, 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, + 32,105,110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, + 42,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46,103, 41, 32,105, +110, 99,111,108, 46,103, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,103, 32, 61, 32,111,117,116, + 99,111,108, 46,103, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 59, 10, 9,105,102, + 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32, 99,111,108, 59, 32, +101,108,115,101, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105,100, + 32,109,116,101,120, 95,114,103, 98, 95,104,117,101, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32, +116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32, +111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109, +105,120, 95,104,117,101, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, + 46, 48, 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105, +110, 99,111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95,114,103, 98, 95,115, 97,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111, +108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118, +101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, 95,115, 97, +116, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, +118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99,111,108, 46, +114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95, +118, 97,108, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108, +111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105, +110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, 95,118, 97,108, 40,102, 97, 99, +116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, 40, +116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99,111,108, 46,114,103, 98, 32, 61, + 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95, 99,111,108,111,114, + 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, + 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111, +108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, 95, 99,111,108,111,114, 40,102, 97, 99,116, + 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, 40,116, +101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99,111,108, 46,114,103, 98, 32, 61, 32, + 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, + 40,105,110,111,117,116, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111, +117,116, 32,102,108,111, 97,116, 32,102, 97, 99,109, 41, 10,123, 10, 9,102, 97, 99,116, 32, 42, 61, 32, 97, 98,115, 40,102, 97, + 99,103, 41, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9,105,102, 40,102, 97, 99,103, + 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32,102, 97, 99,116, 59, 10, 9, 9, +102, 97, 99,116, 32, 61, 32,102, 97, 99,109, 59, 10, 9, 9,102, 97, 99,109, 32, 61, 32,116,109,112, 59, 10, 9,125, 10,125, 10, + 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,111,117,116, + 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102, +108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102, +108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, + 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101, +120, 99,111,108, 32, 43, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95,118, 97,108,117,101, 95,109,117,108, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116, +101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111, +117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9, +109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, + 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99,103, 59, 10, 9,105,110, 99,111,108, 32, 61, + 32, 40,102, 97, 99,109, 32, 43, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10,125, 10, + 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,115, 99,114,101,101,110, 40,102,108,111, 97,116, 32,111,117, 116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32, 102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9, 102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99, -116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, 32,102, 97, 99,116, 59, 10, 9, -105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, - 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,118, 40,102,108,111, 97,116, 32,111,117,116, 99,111, -108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, - 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, - 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32, -102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,105,102, 40,116,101,120, 99,111,108, 32, 33, 61, 32, 48, 46, 48, 41, - 10, 9, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42,111,117, -116, 99,111,108, 47,116,101,120, 99,111,108, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 32, 61, 32, 48, 46, 48, - 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,102,102, 40,102,108,111, 97,116, 32, -111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, - 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, - 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, - 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, - 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, 97, 98,115, 40,116,101,120, 99,111,108, 32, 45, 32,111,117,116, 99, -111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100, 97,114,107, 40,102,108,111, - 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, - 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, - 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114, -115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, - 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, - 41, 32,105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99, -111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,108,105,103,104,116, 40,102,108,111, - 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, - 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, - 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114, -115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, - 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, - 41, 32,105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99, -111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95, 99,108, 97,109,112, 95,112,111,115, -105,116,105,118,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, 97, - 99, 41, 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32,109, 97,120, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, - 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,102, 97, 99, - 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, 97, 99, 41, 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32, - 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95,104, 97,114, 95,100,105,118,105,100,101, 40,102,108,111, 97,116, 32,104, 97,114, 44, 32,111,117,116, 32,102,108,111, - 97,116, 32,111,117,116,104, 97,114, 41, 10,123, 10, 9,111,117,116,104, 97,114, 32, 61, 32,104, 97,114, 47, 49, 50, 56, 46, 48, - 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,104, 97,114, 95,109,117,108,116,105,112,108,121, 95, 99,108, 97,109, -112, 40,102,108,111, 97,116, 32,104, 97,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,104, 97,114, 41, 10,123, - 10, 9,104, 97,114, 32, 42, 61, 32, 49, 50, 56, 46, 48, 59, 10, 10, 9,105,102, 40,104, 97,114, 32, 60, 32, 49, 46, 48, 41, 32, -111,117,116,104, 97,114, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,104, 97,114, 32, 62, 32, 53, 49, 49, - 46, 48, 41, 32,111,117,116,104, 97,114, 32, 61, 32, 53, 49, 49, 46, 48, 59, 10, 9,101,108,115,101, 32,111,117,116,104, 97,114, - 32, 61, 32,104, 97,114, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 97,108,112,104, 97, 95,102,114,111,109, 95, - 99,111,108, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 41, 10,123, - 10, 9, 97,108,112,104, 97, 32, 61, 32, 99,111,108, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 97,108, -112,104, 97, 95,116,111, 95, 99,111,108, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, - 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118, -101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 97,108,112,104, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101, -120, 95,114,103, 98,116,111,105,110,116, 40,118,101, 99, 52, 32,114,103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105, -110,116,101,110,115,105,116,121, 41, 10,123, 10, 9,105,110,116,101,110,115,105,116,121, 32, 61, 32,100,111,116, 40,118,101, 99, - 51, 40, 48, 46, 51, 53, 44, 32, 48, 46, 52, 53, 44, 32, 48, 46, 50, 41, 44, 32,114,103, 98, 46,114,103, 98, 41, 59, 10,125, 10, - 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,105,110,118,101,114,116, 40,102,108,111, 97,116, 32,105,110, -118, 97,108,117,101, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108,117,101, 41, 10,123, 10, 9,111,117, -116,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 32, 45, 32,105,110,118, 97,108,117,101, 59, 10,125, 10, 10,118,111,105,100, 32, -109,116,101,120, 95,114,103, 98, 95,105,110,118,101,114,116, 40,118,101, 99, 52, 32,105,110,114,103, 98, 44, 32,111,117,116, 32, -118,101, 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,118,101, - 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,105,110,114,103, 98, 46,114,103, 98, 44, 32,105,110,114,103, 98, 46, 97, 41, 59, 10,125, - 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, 32, -115,116,101,110, 99,105,108, 44, 32,102,108,111, 97,116, 32,105,110,116,101,110,115,105,116,121, 44, 32,111,117,116, 32,102,108, -111, 97,116, 32,111,117,116,115,116,101,110, 99,105,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,105,110,116, -101,110,115,105,116,121, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,116, 32, 61, 32,105,110,116,101,110,115,105,116, -121, 59, 10, 9,111,117,116,105,110,116,101,110,115,105,116,121, 32, 61, 32,105,110,116,101,110,115,105,116,121, 42,115,116,101, -110, 99,105,108, 59, 10, 9,111,117,116,115,116,101,110, 99,105,108, 32, 61, 32,115,116,101,110, 99,105,108, 42,102, 97, 99,116, - 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, - 32,115,116,101,110, 99,105,108, 44, 32,118,101, 99, 52, 32,114,103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117, -116,115,116,101,110, 99,105,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,102,108, -111, 97,116, 32,102, 97, 99,116, 32, 61, 32,114,103, 98, 46, 97, 59, 10, 9,111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, - 40,114,103, 98, 46,114,103, 98, 44, 32,114,103, 98, 46, 97, 42,115,116,101,110, 99,105,108, 41, 59, 10, 9,111,117,116,115,116, -101,110, 99,105,108, 32, 61, 32,115,116,101,110, 99,105,108, 42,102, 97, 99,116, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95,109, 97,112,112,105,110,103, 95,111,102,115, 40,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32, -111,102,115, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101, -120, 99,111, 32, 61, 32,116,101,120, 99,111, 32, 43, 32,111,102,115, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, -109, 97,112,112,105,110,103, 95,115,105,122,101, 40,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32,115,105, -122,101, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101,120, - 99,111, 32, 61, 32,115,105,122,101, 42,116,101,120, 99,111, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 50,100, - 95,109, 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118, -101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118,101, 99, 51, 40,118,101, 99, 46,120,121, 42, 48, 46, 53, 32, - 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 32, 48, 46, 53, 41, 44, 32,118,101, 99, 46,122, 41, 59, 10,125, 10, 10,118,111,105, -100, 32,109,116,101,120, 95,105,109, 97,103,101, 40,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,115, 97,109,112,108,101,114, - 50, 68, 32,105,109, 97, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, - 52, 32, 99,111,108,111,114, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, - 97, 44, 32,116,101,120, 99,111, 46,120,121, 41, 59, 10, 9,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118, -111,105,100, 32,109,116,101,120, 95,110,111,114,109, 97,108, 40,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,115, 97,109,112, -108,101,114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, - 47, 32, 84,104,101, 32,105,110,118,101,114,116, 32,111,102, 32,116,104,101, 32,114,101,100, 32, 99,104, 97,110,110,101,108, 32, -105,115, 32,116,111, 32,109, 97,107,101, 10, 9, 47, 47, 32,116,104,101, 32,110,111,114,109, 97,108, 32,109, 97,112, 32, 99,111, -109,112,108,105, 97,110,116, 32,119,105,116,104, 32,116,104,101, 32,111,117,116,115,105,100,101, 32,119,111,114,108,100, 46, 10, - 9, 47, 47, 32, 73,116, 32,110,101,101,100,115, 32,116,111, 32, 98,101, 32,100,111,110,101, 32, 98,101, 99, 97,117,115,101, 32, -105,110, 32, 66,108,101,110,100,101,114, 10, 9, 47, 47, 32,116,104,101, 32,110,111,114,109, 97,108, 32,117,115,101,100, 32,112, -111,105,110,116,115, 32,105,110,119, 97,114,100, 46, 10, 9, 47, 47, 32, 83,104,111,117,108,100, 32,116,104,105,115, 32,101,118, -101,114, 32, 99,104, 97,110,103,101, 32,116,104,105,115, 32,110,101,103, 97,116,101, 32,109,117,115,116, 32, 98,101, 32,114,101, -109,111,118,101,100, 46, 10, 32, 32, 32, 32,118,101, 99, 52, 32, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114,101, 50, - 68, 40,105,109, 97, 44, 32,116,101,120, 99,111, 46,120,121, 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32, 50, 46, 48, 42, - 40,118,101, 99, 51, 40, 45, 99,111,108,111,114, 46,114, 44, 32, 99,111,108,111,114, 46,103, 44, 32, 99,111,108,111,114, 46, 98, - 41, 32, 45, 32,118,101, 99, 51, 40, 45, 48, 46, 53, 44, 32, 48, 46, 53, 44, 32, 48, 46, 53, 41, 41, 59, 10,125, 10, 10,118,111, -105,100, 32,109,116,101,120, 95, 98,117,109,112, 95,110,111,114,109, 97,108,115, 95,105,110,105,116, 40, 32,118,101, 99, 51, 32, -118, 78, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 78,111,114,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 78, 97, - 99, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 32, 41, 10,123, - 10, 9,118, 78,111,114,103, 32, 61, 32,118, 78, 59, 10, 9,118, 78, 97, 99, 99, 32, 61, 32,118, 78, 59, 10, 9,102, 80,114,101, -118, 77, 97,103,110,105,116,117,100,101, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10, 47, 42, 42, 32,104,101,108,112,101,114, 32, -109,101,116,104,111,100, 32,116,111, 32,101,120,116,114, 97, 99,116, 32,116,104,101, 32,117,112,112,101,114, 32,108,101,102,116, - 32, 51,120, 51, 32,109, 97,116,114,105,120, 32,102,114,111,109, 32, 97, 32, 52,120, 52, 32,109, 97,116,114,105,120, 32, 42, 47, - 10,109, 97,116, 51, 32,116,111, 95,109, 97,116, 51, 40,109, 97,116, 52, 32,109, 52, 41, 10,123, 10, 9,109, 97,116, 51, 32,109, - 51, 59, 10, 9,109, 51, 91, 48, 93, 32, 61, 32,109, 52, 91, 48, 93, 46,120,121,122, 59, 10, 9,109, 51, 91, 49, 93, 32, 61, 32, -109, 52, 91, 49, 93, 46,120,121,122, 59, 10, 9,109, 51, 91, 50, 93, 32, 61, 32,109, 52, 91, 50, 93, 46,120,121,122, 59, 10, 9, -114,101,116,117,114,110, 32,109, 51, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117,109,112, 95,105,110,105, -116, 95,111, 98,106,115,112, 97, 99,101, 40, 32,118,101, 99, 51, 32,115,117,114,102, 95,112,111,115, 44, 32,118,101, 99, 51, 32, -115,117,114,102, 95,110,111,114,109, 44, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32,109, 97,116, 52, 32,109, 86,105,101,119, 44, 32, -109, 97,116, 52, 32,109, 86,105,101,119, 73,110,118, 44, 32,109, 97,116, 52, 32,109, 79, 98,106, 44, 32,109, 97,116, 52, 32,109, - 79, 98,106, 73,110,118, 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32,102,108,111, 97,116, 32,102, 80,114,101,118, 77, 97,103, -110,105,116,117,100,101, 95,105,110, 44, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 9, - 9, 32, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,111,117,116, 44, - 32,111,117,116, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,111,117,116, 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32,111, -117,116, 32,118,101, 99, 51, 32,118, 82, 49, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 82, 50, 44, 32,111,117,116, 32,102, -108,111, 97,116, 32,102, 68,101,116, 32, 41, 32, 10,123, 10, 9,109, 97,116, 51, 32,111, 98,106, 50,118,105,101,119, 32, 61, 32, -116,111, 95,109, 97,116, 51, 40,103,108, 95, 77,111,100,101,108, 86,105,101,119, 77, 97,116,114,105,120, 41, 59, 10, 9,109, 97, -116, 51, 32,118,105,101,119, 50,111, 98,106, 32, 61, 32,116,111, 95,109, 97,116, 51, 40,103,108, 95, 77,111,100,101,108, 86,105, -101,119, 77, 97,116,114,105,120, 73,110,118,101,114,115,101, 41, 59, 10, 9, 10, 9,118,101, 99, 51, 32,118, 83,105,103,109, 97, - 83, 32, 61, 32,118,105,101,119, 50,111, 98,106, 32, 42, 32,100, 70,100,120, 40, 32,115,117,114,102, 95,112,111,115, 32, 41, 59, - 10, 9,118,101, 99, 51, 32,118, 83,105,103,109, 97, 84, 32, 61, 32,118,105,101,119, 50,111, 98,106, 32, 42, 32,100, 70,100,121, - 40, 32,115,117,114,102, 95,112,111,115, 32, 41, 59, 10, 9,118,101, 99, 51, 32,118, 78, 32, 61, 32,110,111,114,109, 97,108,105, -122,101, 40, 32,115,117,114,102, 95,110,111,114,109, 32, 42, 32,111, 98,106, 50,118,105,101,119, 32, 41, 59, 10, 10, 9,118, 82, - 49, 32, 61, 32, 99,114,111,115,115, 40, 32,118, 83,105,103,109, 97, 84, 44, 32,118, 78, 32, 41, 59, 10, 9,118, 82, 50, 32, 61, - 32, 99,114,111,115,115, 40, 32,118, 78, 44, 32,118, 83,105,103,109, 97, 83, 32, 41, 32, 59, 10, 9,102, 68,101,116, 32, 61, 32, -100,111,116, 32, 40, 32,118, 83,105,103,109, 97, 83, 44, 32,118, 82, 49, 32, 41, 59, 10, 9, 10, 9, 47, 42, 32,112,114,101,116, -114, 97,110,115,102,111,114,109, 32,118, 78, 97, 99, 99, 32, 40,105,110, 32,109,116,101,120, 95, 98,117,109,112, 95, 97,112,112, -108,121, 41, 32,117,115,105,110,103, 32,116,104,101, 32,105,110,118,101,114,115,101, 32,116,114, 97,110,115,112,111,115,101,100, - 32, 42, 47, 10, 9,118, 82, 49, 32, 61, 32,118, 82, 49, 32, 42, 32,118,105,101,119, 50,111, 98,106, 59, 10, 9,118, 82, 50, 32, - 61, 32,118, 82, 50, 32, 42, 32,118,105,101,119, 50,111, 98,106, 59, 10, 9,118, 78, 32, 61, 32,118, 78, 32, 42, 32,118,105,101, -119, 50,111, 98,106, 59, 10, 9, 10, 9,102,108,111, 97,116, 32,102, 77, 97,103,110,105,116,117,100,101, 32, 61, 32, 97, 98,115, - 40,102, 68,101,116, 41, 32, 42, 32,108,101,110,103,116,104, 40,118, 78, 41, 59, 10, 9,118, 78, 97, 99, 99, 95,111,117,116, 32, - 61, 32,118, 78, 97, 99, 99, 95,105,110, 32, 42, 32, 40,102, 77, 97,103,110,105,116,117,100,101, 32, 47, 32,102, 80,114,101,118, - 77, 97,103,110,105,116,117,100,101, 95,105,110, 41, 59, 10, 9,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,111, -117,116, 32, 61, 32,102, 77, 97,103,110,105,116,117,100,101, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117, -109,112, 95,105,110,105,116, 95,116,101,120,116,117,114,101,115,112, 97, 99,101, 40, 32,118,101, 99, 51, 32,115,117,114,102, 95, -112,111,115, 44, 32,118,101, 99, 51, 32,115,117,114,102, 95,110,111,114,109, 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, -102,108,111, 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,105,110, 44, 32,118,101, 99, 51, 32,118, 78, - 97, 99, 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 80,114,101, -118, 77, 97,103,110,105,116,117,100,101, 95,111,117,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,111, -117,116, 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32,111,117,116, 32,118,101, 99, 51, 32,118, 82, 49, 44, 32,111,117,116, - 32,118,101, 99, 51, 32,118, 82, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 68,101,116, 32, 41, 32, 10,123, 10, 9, -118,101, 99, 51, 32,118, 83,105,103,109, 97, 83, 32, 61, 32,100, 70,100,120, 40, 32,115,117,114,102, 95,112,111,115, 32, 41, 59, - 10, 9,118,101, 99, 51, 32,118, 83,105,103,109, 97, 84, 32, 61, 32,100, 70,100,121, 40, 32,115,117,114,102, 95,112,111,115, 32, - 41, 59, 10, 9,118,101, 99, 51, 32,118, 78, 32, 61, 32,115,117,114,102, 95,110,111,114,109, 59, 32, 47, 42, 32,110,111,114,109, - 97,108,105,122,101,100, 32,105,110,116,101,114,112,111,108, 97,116,101,100, 32,118,101,114,116,101,120, 32,110,111,114,109, 97, -108, 32, 42, 47, 10, 9, 10, 9,118, 82, 49, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 32, 99,114,111,115,115, 40, 32, -118, 83,105,103,109, 97, 84, 44, 32,118, 78, 32, 41, 32, 41, 59, 10, 9,118, 82, 50, 32, 61, 32,110,111,114,109, 97,108,105,122, -101, 40, 32, 99,114,111,115,115, 40, 32,118, 78, 44, 32,118, 83,105,103,109, 97, 83, 32, 41, 32, 41, 59, 10, 9,102, 68,101,116, - 32, 61, 32,115,105,103,110, 40, 32,100,111,116, 40,118, 83,105,103,109, 97, 83, 44, 32,118, 82, 49, 41, 32, 41, 59, 10, 9, 10, - 9,102,108,111, 97,116, 32,102, 77, 97,103,110,105,116,117,100,101, 32, 61, 32, 97, 98,115, 40,102, 68,101,116, 41, 59, 10, 9, -118, 78, 97, 99, 99, 95,111,117,116, 32, 61, 32,118, 78, 97, 99, 99, 95,105,110, 32, 42, 32, 40,102, 77, 97,103,110,105,116,117, -100,101, 32, 47, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,105,110, 41, 59, 10, 9,102, 80,114,101,118, 77, - 97,103,110,105,116,117,100,101, 95,111,117,116, 32, 61, 32,102, 77, 97,103,110,105,116,117,100,101, 59, 10,125, 10, 10,118,111, -105,100, 32,109,116,101,120, 95, 98,117,109,112, 95,105,110,105,116, 95,118,105,101,119,115,112, 97, 99,101, 40, 32,118,101, 99, - 51, 32,115,117,114,102, 95,112,111,115, 44, 32,118,101, 99, 51, 32,115,117,114,102, 95,110,111,114,109, 44, 32, 10, 9, 9, 9, - 9, 9, 9, 9, 32, 32, 32,102,108,111, 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,105,110, 44, 32, -118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32,111,117,116, 32,102,108,111, - 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,111,117,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32, -118, 78, 97, 99, 99, 95,111,117,116, 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32,111,117,116, 32,118,101, 99, 51, 32,118, - 82, 49, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 82, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 68,101,116, - 32, 41, 32, 10,123, 10, 9,118,101, 99, 51, 32,118, 83,105,103,109, 97, 83, 32, 61, 32,100, 70,100,120, 40, 32,115,117,114,102, - 95,112,111,115, 32, 41, 59, 10, 9,118,101, 99, 51, 32,118, 83,105,103,109, 97, 84, 32, 61, 32,100, 70,100,121, 40, 32,115,117, -114,102, 95,112,111,115, 32, 41, 59, 10, 9,118,101, 99, 51, 32,118, 78, 32, 61, 32,115,117,114,102, 95,110,111,114,109, 59, 32, - 47, 42, 32,110,111,114,109, 97,108,105,122,101,100, 32,105,110,116,101,114,112,111,108, 97,116,101,100, 32,118,101,114,116,101, -120, 32,110,111,114,109, 97,108, 32, 42, 47, 10, 9, 10, 9,118, 82, 49, 32, 61, 32, 99,114,111,115,115, 40, 32,118, 83,105,103, -109, 97, 84, 44, 32,118, 78, 32, 41, 59, 10, 9,118, 82, 50, 32, 61, 32, 99,114,111,115,115, 40, 32,118, 78, 44, 32,118, 83,105, -103,109, 97, 83, 32, 41, 32, 59, 10, 9,102, 68,101,116, 32, 61, 32,100,111,116, 32, 40, 32,118, 83,105,103,109, 97, 83, 44, 32, -118, 82, 49, 32, 41, 59, 10, 9, 10, 9,102,108,111, 97,116, 32,102, 77, 97,103,110,105,116,117,100,101, 32, 61, 32, 97, 98,115, - 40,102, 68,101,116, 41, 59, 10, 9,118, 78, 97, 99, 99, 95,111,117,116, 32, 61, 32,118, 78, 97, 99, 99, 95,105,110, 32, 42, 32, - 40,102, 77, 97,103,110,105,116,117,100,101, 32, 47, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,105,110, 41, - 59, 10, 9,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,111,117,116, 32, 61, 32,102, 77, 97,103,110,105,116,117, -100,101, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117,109,112, 95,116, 97,112, 51, 40, 32,118,101, 99, 51, - 32,116,101,120, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,102,108,111, 97,116, 32,104, 83, 99, - 97,108,101, 44, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,111,117,116, 32,102, -108,111, 97,116, 32,100, 66,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,116, 32, 41, 32, 10,123, 10, 9,118,101, - 99, 50, 32, 83, 84,108,108, 32, 61, 32,116,101,120, 99,111, 46,120,121, 59, 10, 9,118,101, 99, 50, 32, 83, 84,108,114, 32, 61, - 32,116,101,120, 99,111, 46,120,121, 32, 43, 32,100, 70,100,120, 40,116,101,120, 99,111, 46,120,121, 41, 32, 59, 10, 9,118,101, - 99, 50, 32, 83, 84,117,108, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 43, 32,100, 70,100,121, 40,116,101,120, 99,111, 46, -120,121, 41, 32, 59, 10, 9, 10, 9,102,108,111, 97,116, 32, 72,108,108, 44, 72,108,114, 44, 72,117,108, 59, 10, 9,114,103, 98, -116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,108,108, 41, 44, 32, 72,108,108, 32, - 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,108,114, - 41, 44, 32, 72,108,114, 32, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, - 97, 44, 32, 83, 84,117,108, 41, 44, 32, 72,117,108, 32, 41, 59, 10, 9, 10, 9,100, 66,115, 32, 61, 32,104, 83, 99, 97,108,101, - 32, 42, 32, 40, 72,108,114, 32, 45, 32, 72,108,108, 41, 59, 10, 9,100, 66,116, 32, 61, 32,104, 83, 99, 97,108,101, 32, 42, 32, - 40, 72,117,108, 32, 45, 32, 72,108,108, 41, 59, 10,125, 10, 10, 35,105,102,100,101,102, 32, 66, 85, 77, 80, 95, 66, 73, 67, 85, - 66, 73, 67, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117,109,112, 95, 98,105, 99,117, 98,105, 99, 40, 32,118,101, 99, - 51, 32,116,101,120, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,102,108,111, 97,116, 32,104, 83, - 99, 97,108,101, 44, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,111,117,116, 32, -102,108,111, 97,116, 32,100, 66,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,116, 32, 41, 32, 10,123, 10, 9,102, -108,111, 97,116, 32, 72,108, 59, 10, 9,102,108,111, 97,116, 32, 72,114, 59, 10, 9,102,108,111, 97,116, 32, 72,100, 59, 10, 9, -102,108,111, 97,116, 32, 72,117, 59, 10, 9, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,120, 32, 61, 32,100, 70,100,120, 40,116, -101,120, 99,111, 46,120,121, 41, 59, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,121, 32, 61, 32,100, 70,100,121, 40,116,101,120, - 99,111, 46,120,121, 41, 59, 10, 32, 10, 9,118,101, 99, 50, 32, 83, 84,108, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 45, - 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,120, 32, 59, 10, 9,118,101, 99, 50, 32, 83, 84,114, 32, 61, 32,116,101,120, 99,111, - 46,120,121, 32, 43, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,120, 32, 59, 10, 9,118,101, 99, 50, 32, 83, 84,100, 32, 61, 32, -116,101,120, 99,111, 46,120,121, 32, 45, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,121, 32, 59, 10, 9,118,101, 99, 50, 32, 83, - 84,117, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 43, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,121, 32, 59, 10, 9, 10, - 9,114,103, 98,116,111, 98,119, 40,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,108, 41, 44, 32, 72,108, - 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,114, 41, 44, - 32, 72,114, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84, -100, 41, 44, 32, 72,100, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, - 32, 83, 84,117, 41, 44, 32, 72,117, 41, 59, 10, 9, 10, 9,118,101, 99, 50, 32,100, 72,100,120,121, 32, 61, 32,118,101, 99, 50, - 40, 72,114, 32, 45, 32, 72,108, 44, 32, 72,117, 32, 45, 32, 72,100, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 66,108,101,110, -100, 32, 61, 32, 99,108, 97,109,112, 40, 49, 46, 48, 45,116,101,120,116,117,114,101, 81,117,101,114,121, 76, 79, 68, 40,105,109, - 97, 44, 32,116,101,120, 99,111, 46,120,121, 41, 46,120, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,105,102, 40,102, - 66,108,101,110,100, 33, 61, 48, 46, 48, 41, 10, 9,123, 10, 9, 9, 47, 47, 32,116,104,101, 32,100,101,114,105,118, 97,116,105, -118,101, 32,111,102, 32,116,104,101, 32, 98,105, 99,117, 98,105, 99, 32,115, 97,109,112,108,105,110,103, 32,111,102, 32,108,101, -118,101,108, 32, 48, 10, 9, 9,105,118,101, 99, 50, 32,118, 68,105,109, 59, 10, 9, 9,118, 68,105,109, 32, 61, 32,116,101,120, -116,117,114,101, 83,105,122,101, 40,105,109, 97, 44, 32, 48, 41, 59, 10, 10, 9, 9, 47, 47, 32,116, 97,107,105,110,103, 32,116, -104,101, 32,102,114, 97, 99,116, 32,112, 97,114,116, 32,111,102, 32,116,104,101, 32,116,101,120,116,117,114,101, 32, 99,111,111, -114,100,105,110, 97,116,101, 32,105,115, 32, 97, 32,104, 97,114,100, 99,111,100,101,100, 32,119,114, 97,112, 32,109,111,100,101, - 46, 10, 9, 9, 47, 47, 32,116,104,105,115, 32,105,115, 32, 97, 99, 99,101,112,116, 97, 98,108,101, 32, 97,115, 32,116,101,120, -116,117,114,101,115, 32,117,115,101, 32,119,114, 97,112, 32,109,111,100,101, 32,101,120, 99,108,117,115,105,118,101,108,121, 32, -105,110, 32, 51, 68, 32,118,105,101,119, 32,101,108,115,101,119,104,101,114,101, 32,105,110, 32, 98,108,101,110,100,101,114, 46, - 32, 10, 9, 9, 47, 47, 32,116,104,105,115, 32,105,115, 32,100,111,110,101, 32,115,111, 32,116,104, 97,116, 32,119,101, 32, 99, - 97,110, 32,115,116,105,108,108, 32,103,101,116, 32, 97, 32,118, 97,108,105,100, 32,116,101,120,101,108, 32,119,105,116,104, 32, -117,118,115, 32,111,117,116,115,105,100,101, 32,116,104,101, 32, 48, 44, 49, 32,114, 97,110,103,101, 10, 9, 9, 47, 47, 32, 98, -121, 32,116,101,120,101,108, 70,101,116, 99,104, 32, 98,101,108,111,119, 44, 32, 97,115, 32, 99,111,111,114,100,105,110, 97,116, -101,115, 32, 97,114,101, 32, 99,108, 97,109,112,101,100, 32,119,104,101,110, 32,117,115,105,110,103, 32,116,104,105,115, 32,102, -117,110, 99,116,105,111,110, 46, 10, 9, 9,118,101, 99, 50, 32,102, 84,101,120, 76,111, 99, 32, 61, 32,118, 68,105,109, 42,102, -114, 97, 99,116, 40,116,101,120, 99,111, 46,120,121, 41, 32, 45, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 32, 48, 46, 53, 41, 59, - 10, 9, 9,105,118,101, 99, 50, 32,105, 84,101,120, 76,111, 99, 32, 61, 32,105,118,101, 99, 50, 40,102,108,111,111,114, 40,102, - 84,101,120, 76,111, 99, 41, 41, 59, 10, 9, 9,118,101, 99, 50, 32,116, 32, 61, 32, 99,108, 97,109,112, 40,102, 84,101,120, 76, -111, 99, 32, 45, 32,105, 84,101,120, 76,111, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 9, 9, 47, 47, 32,115, 97,116, - 32,106,117,115,116, 32,116,111, 32, 98,101, 32,112,101,100, 97,110,116,105, 99, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, +116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, + 97, 99,103, 59, 10, 9,105,110, 99,111,108, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32,102, 97, 99,116, + 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,115,117, 98, 40,102,108,111, 97,116, 32,111,117, +116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32, +102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9, +102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99, +116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, 32, 45,102, 97, 99,116, 59, 10, + 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, + 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95, 97,100,100, 40,102,108,111, 97,116, 32,111,117,116, 99, +111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108, +111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108, +111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, + 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, 32,102, 97, 99,116, 59, 10, 9,105,110, + 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,118, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, + 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, + 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, + 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,105,102, 40,116,101,120, 99,111,108, 32, 33, 61, 32, 48, 46, 48, 41, 10, 9, + 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99, +111,108, 47,116,101,120, 99,111,108, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 32, 61, 32, 48, 46, 48, 59, 10, +125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,102,102, 40,102,108,111, 97,116, 32,111,117, +116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32, +102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9, +102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99, +116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111, +117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, 97, 98,115, 40,116,101,120, 99,111,108, 32, 45, 32,111,117,116, 99,111,108, + 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100, 97,114,107, 40,102,108,111, 97,116, + 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99, +116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10, +123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40, +102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, 32, 61, + 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 41, 32, +105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99,111,108, + 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,108,105,103,104,116, 40,102,108,111, 97,116, + 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99, +116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10, +123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40, +102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, 32, 61, + 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 41, 32, +105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99,111,108, + 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95, 99,108, 97,109,112, 95,112,111,115,105,116, +105,118,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, 97, 99, 41, + 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32,109, 97,120, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, 97, 99, 41, 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32, 99,108, + 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95,104, 97,114, 95,100,105,118,105,100,101, 40,102,108,111, 97,116, 32,104, 97,114, 44, 32,111,117,116, 32,102,108,111, 97,116, + 32,111,117,116,104, 97,114, 41, 10,123, 10, 9,111,117,116,104, 97,114, 32, 61, 32,104, 97,114, 47, 49, 50, 56, 46, 48, 59, 10, +125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,104, 97,114, 95,109,117,108,116,105,112,108,121, 95, 99,108, 97,109,112, 40, +102,108,111, 97,116, 32,104, 97,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,104, 97,114, 41, 10,123, 10, 9, +104, 97,114, 32, 42, 61, 32, 49, 50, 56, 46, 48, 59, 10, 10, 9,105,102, 40,104, 97,114, 32, 60, 32, 49, 46, 48, 41, 32,111,117, +116,104, 97,114, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,104, 97,114, 32, 62, 32, 53, 49, 49, 46, 48, + 41, 32,111,117,116,104, 97,114, 32, 61, 32, 53, 49, 49, 46, 48, 59, 10, 9,101,108,115,101, 32,111,117,116,104, 97,114, 32, 61, + 32,104, 97,114, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 97,108,112,104, 97, 95,102,114,111,109, 95, 99,111, +108, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 41, 10,123, 10, 9, + 97,108,112,104, 97, 32, 61, 32, 99,111,108, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 97,108,112,104, + 97, 95,116,111, 95, 99,111,108, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 44, 32, +111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, + 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 97,108,112,104, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, +114,103, 98,116,111,105,110,116, 40,118,101, 99, 52, 32,114,103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,116, +101,110,115,105,116,121, 41, 10,123, 10, 9,105,110,116,101,110,115,105,116,121, 32, 61, 32,100,111,116, 40,118,101, 99, 51, 40, + 48, 46, 51, 53, 44, 32, 48, 46, 52, 53, 44, 32, 48, 46, 50, 41, 44, 32,114,103, 98, 46,114,103, 98, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,105,110,118,101,114,116, 40,102,108,111, 97,116, 32,105,110,118, 97, +108,117,101, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108,117,101, 41, 10,123, 10, 9,111,117,116,118, + 97,108,117,101, 32, 61, 32, 49, 46, 48, 32, 45, 32,105,110,118, 97,108,117,101, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, +101,120, 95,114,103, 98, 95,105,110,118,101,114,116, 40,118,101, 99, 52, 32,105,110,114,103, 98, 44, 32,111,117,116, 32,118,101, + 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,118,101, 99, 51, + 40, 49, 46, 48, 41, 32, 45, 32,105,110,114,103, 98, 46,114,103, 98, 44, 32,105,110,114,103, 98, 46, 97, 41, 59, 10,125, 10, 10, +118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, 32,115,116, +101,110, 99,105,108, 44, 32,102,108,111, 97,116, 32,105,110,116,101,110,115,105,116,121, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,111,117,116,115,116,101,110, 99,105,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,105,110,116,101,110, +115,105,116,121, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,116, 32, 61, 32,105,110,116,101,110,115,105,116,121, 59, + 10, 9,111,117,116,105,110,116,101,110,115,105,116,121, 32, 61, 32,105,110,116,101,110,115,105,116,121, 42,115,116,101,110, 99, +105,108, 59, 10, 9,111,117,116,115,116,101,110, 99,105,108, 32, 61, 32,115,116,101,110, 99,105,108, 42,102, 97, 99,116, 59, 10, +125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, 32,115, +116,101,110, 99,105,108, 44, 32,118,101, 99, 52, 32,114,103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115, +116,101,110, 99,105,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,102,108,111, 97, +116, 32,102, 97, 99,116, 32, 61, 32,114,103, 98, 46, 97, 59, 10, 9,111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,114, +103, 98, 46,114,103, 98, 44, 32,114,103, 98, 46, 97, 42,115,116,101,110, 99,105,108, 41, 59, 10, 9,111,117,116,115,116,101,110, + 99,105,108, 32, 61, 32,115,116,101,110, 99,105,108, 42,102, 97, 99,116, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95,109, 97,112,112,105,110,103, 95,111,102,115, 40,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32,111,102, +115, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101,120, 99, +111, 32, 61, 32,116,101,120, 99,111, 32, 43, 32,111,102,115, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,109, 97, +112,112,105,110,103, 95,115,105,122,101, 40,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32,115,105,122,101, + 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101,120, 99,111, + 32, 61, 32,115,105,122,101, 42,116,101,120, 99,111, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 50,100, 95,109, + 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, + 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118,101, 99, 51, 40,118,101, 99, 46,120,121, 42, 48, 46, 53, 32, 43, 32, +118,101, 99, 50, 40, 48, 46, 53, 44, 32, 48, 46, 53, 41, 44, 32,118,101, 99, 46,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32, +109,116,101,120, 95,105,109, 97,103,101, 40,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, + 32,105,109, 97, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, + 99,111,108,111,114, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, + 32,116,101,120, 99,111, 46,120,121, 41, 59, 10, 9,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105, +100, 32,109,116,101,120, 95,110,111,114,109, 97,108, 40,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,115, 97,109,112,108,101, +114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 47, 32, + 84,104,101, 32,105,110,118,101,114,116, 32,111,102, 32,116,104,101, 32,114,101,100, 32, 99,104, 97,110,110,101,108, 32,105,115, + 32,116,111, 32,109, 97,107,101, 10, 9, 47, 47, 32,116,104,101, 32,110,111,114,109, 97,108, 32,109, 97,112, 32, 99,111,109,112, +108,105, 97,110,116, 32,119,105,116,104, 32,116,104,101, 32,111,117,116,115,105,100,101, 32,119,111,114,108,100, 46, 10, 9, 47, + 47, 32, 73,116, 32,110,101,101,100,115, 32,116,111, 32, 98,101, 32,100,111,110,101, 32, 98,101, 99, 97,117,115,101, 32,105,110, + 32, 66,108,101,110,100,101,114, 10, 9, 47, 47, 32,116,104,101, 32,110,111,114,109, 97,108, 32,117,115,101,100, 32,112,111,105, +110,116,115, 32,105,110,119, 97,114,100, 46, 10, 9, 47, 47, 32, 83,104,111,117,108,100, 32,116,104,105,115, 32,101,118,101,114, + 32, 99,104, 97,110,103,101, 32,116,104,105,115, 32,110,101,103, 97,116,101, 32,109,117,115,116, 32, 98,101, 32,114,101,109,111, +118,101,100, 46, 10, 32, 32, 32, 32,118,101, 99, 52, 32, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40, +105,109, 97, 44, 32,116,101,120, 99,111, 46,120,121, 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32, 50, 46, 48, 42, 40,118, +101, 99, 51, 40, 45, 99,111,108,111,114, 46,114, 44, 32, 99,111,108,111,114, 46,103, 44, 32, 99,111,108,111,114, 46, 98, 41, 32, + 45, 32,118,101, 99, 51, 40, 45, 48, 46, 53, 44, 32, 48, 46, 53, 44, 32, 48, 46, 53, 41, 41, 59, 10,125, 10, 10,118,111,105,100, + 32,109,116,101,120, 95, 98,117,109,112, 95,110,111,114,109, 97,108,115, 95,105,110,105,116, 40, 32,118,101, 99, 51, 32,118, 78, + 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 78,111,114,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 32, 41, 10,123, 10, 9, +118, 78,111,114,103, 32, 61, 32,118, 78, 59, 10, 9,118, 78, 97, 99, 99, 32, 61, 32,118, 78, 59, 10, 9,102, 80,114,101,118, 77, + 97,103,110,105,116,117,100,101, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10, 47, 42, 42, 32,104,101,108,112,101,114, 32,109,101, +116,104,111,100, 32,116,111, 32,101,120,116,114, 97, 99,116, 32,116,104,101, 32,117,112,112,101,114, 32,108,101,102,116, 32, 51, +120, 51, 32,109, 97,116,114,105,120, 32,102,114,111,109, 32, 97, 32, 52,120, 52, 32,109, 97,116,114,105,120, 32, 42, 47, 10,109, + 97,116, 51, 32,116,111, 95,109, 97,116, 51, 40,109, 97,116, 52, 32,109, 52, 41, 10,123, 10, 9,109, 97,116, 51, 32,109, 51, 59, + 10, 9,109, 51, 91, 48, 93, 32, 61, 32,109, 52, 91, 48, 93, 46,120,121,122, 59, 10, 9,109, 51, 91, 49, 93, 32, 61, 32,109, 52, + 91, 49, 93, 46,120,121,122, 59, 10, 9,109, 51, 91, 50, 93, 32, 61, 32,109, 52, 91, 50, 93, 46,120,121,122, 59, 10, 9,114,101, +116,117,114,110, 32,109, 51, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117,109,112, 95,105,110,105,116, 95, +111, 98,106,115,112, 97, 99,101, 40, 32,118,101, 99, 51, 32,115,117,114,102, 95,112,111,115, 44, 32,118,101, 99, 51, 32,115,117, +114,102, 95,110,111,114,109, 44, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32,109, 97,116, 52, 32,109, 86,105,101,119, 44, 32,109, 97, +116, 52, 32,109, 86,105,101,119, 73,110,118, 44, 32,109, 97,116, 52, 32,109, 79, 98,106, 44, 32,109, 97,116, 52, 32,109, 79, 98, +106, 73,110,118, 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32,102,108,111, 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105, +116,117,100,101, 95,105,110, 44, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 9, 9, 32, + 32,111,117,116, 32,102,108,111, 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,111,117,116, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,111,117,116, 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32,111,117,116, + 32,118,101, 99, 51, 32,118, 82, 49, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 82, 50, 44, 32,111,117,116, 32,102,108,111, + 97,116, 32,102, 68,101,116, 32, 41, 32, 10,123, 10, 9,109, 97,116, 51, 32,111, 98,106, 50,118,105,101,119, 32, 61, 32,116,111, + 95,109, 97,116, 51, 40,103,108, 95, 77,111,100,101,108, 86,105,101,119, 77, 97,116,114,105,120, 41, 59, 10, 9,109, 97,116, 51, + 32,118,105,101,119, 50,111, 98,106, 32, 61, 32,116,111, 95,109, 97,116, 51, 40,103,108, 95, 77,111,100,101,108, 86,105,101,119, + 77, 97,116,114,105,120, 73,110,118,101,114,115,101, 41, 59, 10, 9, 10, 9,118,101, 99, 51, 32,118, 83,105,103,109, 97, 83, 32, + 61, 32,118,105,101,119, 50,111, 98,106, 32, 42, 32,100, 70,100,120, 40, 32,115,117,114,102, 95,112,111,115, 32, 41, 59, 10, 9, +118,101, 99, 51, 32,118, 83,105,103,109, 97, 84, 32, 61, 32,118,105,101,119, 50,111, 98,106, 32, 42, 32,100, 70,100,121, 40, 32, +115,117,114,102, 95,112,111,115, 32, 41, 59, 10, 9,118,101, 99, 51, 32,118, 78, 32, 61, 32,110,111,114,109, 97,108,105,122,101, + 40, 32,115,117,114,102, 95,110,111,114,109, 32, 42, 32,111, 98,106, 50,118,105,101,119, 32, 41, 59, 10, 10, 9,118, 82, 49, 32, + 61, 32, 99,114,111,115,115, 40, 32,118, 83,105,103,109, 97, 84, 44, 32,118, 78, 32, 41, 59, 10, 9,118, 82, 50, 32, 61, 32, 99, +114,111,115,115, 40, 32,118, 78, 44, 32,118, 83,105,103,109, 97, 83, 32, 41, 32, 59, 10, 9,102, 68,101,116, 32, 61, 32,100,111, +116, 32, 40, 32,118, 83,105,103,109, 97, 83, 44, 32,118, 82, 49, 32, 41, 59, 10, 9, 10, 9, 47, 42, 32,112,114,101,116,114, 97, +110,115,102,111,114,109, 32,118, 78, 97, 99, 99, 32, 40,105,110, 32,109,116,101,120, 95, 98,117,109,112, 95, 97,112,112,108,121, + 41, 32,117,115,105,110,103, 32,116,104,101, 32,105,110,118,101,114,115,101, 32,116,114, 97,110,115,112,111,115,101,100, 32, 42, + 47, 10, 9,118, 82, 49, 32, 61, 32,118, 82, 49, 32, 42, 32,118,105,101,119, 50,111, 98,106, 59, 10, 9,118, 82, 50, 32, 61, 32, +118, 82, 50, 32, 42, 32,118,105,101,119, 50,111, 98,106, 59, 10, 9,118, 78, 32, 61, 32,118, 78, 32, 42, 32,118,105,101,119, 50, +111, 98,106, 59, 10, 9, 10, 9,102,108,111, 97,116, 32,102, 77, 97,103,110,105,116,117,100,101, 32, 61, 32, 97, 98,115, 40,102, + 68,101,116, 41, 32, 42, 32,108,101,110,103,116,104, 40,118, 78, 41, 59, 10, 9,118, 78, 97, 99, 99, 95,111,117,116, 32, 61, 32, +118, 78, 97, 99, 99, 95,105,110, 32, 42, 32, 40,102, 77, 97,103,110,105,116,117,100,101, 32, 47, 32,102, 80,114,101,118, 77, 97, +103,110,105,116,117,100,101, 95,105,110, 41, 59, 10, 9,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,111,117,116, + 32, 61, 32,102, 77, 97,103,110,105,116,117,100,101, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117,109,112, + 95,105,110,105,116, 95,116,101,120,116,117,114,101,115,112, 97, 99,101, 40, 32,118,101, 99, 51, 32,115,117,114,102, 95,112,111, +115, 44, 32,118,101, 99, 51, 32,115,117,114,102, 95,110,111,114,109, 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32,102,108, +111, 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,105,110, 44, 32,118,101, 99, 51, 32,118, 78, 97, 99, + 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 80,114,101,118, 77, + 97,103,110,105,116,117,100,101, 95,111,117,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,111,117,116, + 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32,111,117,116, 32,118,101, 99, 51, 32,118, 82, 49, 44, 32,111,117,116, 32,118, +101, 99, 51, 32,118, 82, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 68,101,116, 32, 41, 32, 10,123, 10, 9,118,101, + 99, 51, 32,118, 83,105,103,109, 97, 83, 32, 61, 32,100, 70,100,120, 40, 32,115,117,114,102, 95,112,111,115, 32, 41, 59, 10, 9, +118,101, 99, 51, 32,118, 83,105,103,109, 97, 84, 32, 61, 32,100, 70,100,121, 40, 32,115,117,114,102, 95,112,111,115, 32, 41, 59, + 10, 9,118,101, 99, 51, 32,118, 78, 32, 61, 32,115,117,114,102, 95,110,111,114,109, 59, 32, 47, 42, 32,110,111,114,109, 97,108, +105,122,101,100, 32,105,110,116,101,114,112,111,108, 97,116,101,100, 32,118,101,114,116,101,120, 32,110,111,114,109, 97,108, 32, + 42, 47, 10, 9, 10, 9,118, 82, 49, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 32, 99,114,111,115,115, 40, 32,118, 83, +105,103,109, 97, 84, 44, 32,118, 78, 32, 41, 32, 41, 59, 10, 9,118, 82, 50, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, + 32, 99,114,111,115,115, 40, 32,118, 78, 44, 32,118, 83,105,103,109, 97, 83, 32, 41, 32, 41, 59, 10, 9,102, 68,101,116, 32, 61, + 32,115,105,103,110, 40, 32,100,111,116, 40,118, 83,105,103,109, 97, 83, 44, 32,118, 82, 49, 41, 32, 41, 59, 10, 9, 10, 9,102, +108,111, 97,116, 32,102, 77, 97,103,110,105,116,117,100,101, 32, 61, 32, 97, 98,115, 40,102, 68,101,116, 41, 59, 10, 9,118, 78, + 97, 99, 99, 95,111,117,116, 32, 61, 32,118, 78, 97, 99, 99, 95,105,110, 32, 42, 32, 40,102, 77, 97,103,110,105,116,117,100,101, + 32, 47, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,105,110, 41, 59, 10, 9,102, 80,114,101,118, 77, 97,103, +110,105,116,117,100,101, 95,111,117,116, 32, 61, 32,102, 77, 97,103,110,105,116,117,100,101, 59, 10,125, 10, 10,118,111,105,100, + 32,109,116,101,120, 95, 98,117,109,112, 95,105,110,105,116, 95,118,105,101,119,115,112, 97, 99,101, 40, 32,118,101, 99, 51, 32, +115,117,114,102, 95,112,111,115, 44, 32,118,101, 99, 51, 32,115,117,114,102, 95,110,111,114,109, 44, 32, 10, 9, 9, 9, 9, 9, + 9, 9, 32, 32, 32,102,108,111, 97,116, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,105,110, 44, 32,118,101, + 99, 51, 32,118, 78, 97, 99, 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32,111,117,116, 32,102,108,111, 97,116, + 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,111,117,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 78, + 97, 99, 99, 95,111,117,116, 44, 32, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32,111,117,116, 32,118,101, 99, 51, 32,118, 82, 49, + 44, 32,111,117,116, 32,118,101, 99, 51, 32,118, 82, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 68,101,116, 32, 41, + 32, 10,123, 10, 9,118,101, 99, 51, 32,118, 83,105,103,109, 97, 83, 32, 61, 32,100, 70,100,120, 40, 32,115,117,114,102, 95,112, +111,115, 32, 41, 59, 10, 9,118,101, 99, 51, 32,118, 83,105,103,109, 97, 84, 32, 61, 32,100, 70,100,121, 40, 32,115,117,114,102, + 95,112,111,115, 32, 41, 59, 10, 9,118,101, 99, 51, 32,118, 78, 32, 61, 32,115,117,114,102, 95,110,111,114,109, 59, 32, 47, 42, + 32,110,111,114,109, 97,108,105,122,101,100, 32,105,110,116,101,114,112,111,108, 97,116,101,100, 32,118,101,114,116,101,120, 32, +110,111,114,109, 97,108, 32, 42, 47, 10, 9, 10, 9,118, 82, 49, 32, 61, 32, 99,114,111,115,115, 40, 32,118, 83,105,103,109, 97, + 84, 44, 32,118, 78, 32, 41, 59, 10, 9,118, 82, 50, 32, 61, 32, 99,114,111,115,115, 40, 32,118, 78, 44, 32,118, 83,105,103,109, + 97, 83, 32, 41, 32, 59, 10, 9,102, 68,101,116, 32, 61, 32,100,111,116, 32, 40, 32,118, 83,105,103,109, 97, 83, 44, 32,118, 82, + 49, 32, 41, 59, 10, 9, 10, 9,102,108,111, 97,116, 32,102, 77, 97,103,110,105,116,117,100,101, 32, 61, 32, 97, 98,115, 40,102, + 68,101,116, 41, 59, 10, 9,118, 78, 97, 99, 99, 95,111,117,116, 32, 61, 32,118, 78, 97, 99, 99, 95,105,110, 32, 42, 32, 40,102, + 77, 97,103,110,105,116,117,100,101, 32, 47, 32,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,105,110, 41, 59, 10, + 9,102, 80,114,101,118, 77, 97,103,110,105,116,117,100,101, 95,111,117,116, 32, 61, 32,102, 77, 97,103,110,105,116,117,100,101, + 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117,109,112, 95,116, 97,112, 51, 40, 32,118,101, 99, 51, 32,116, +101,120, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,102,108,111, 97,116, 32,104, 83, 99, 97,108, +101, 44, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,111,117,116, 32,102,108,111, + 97,116, 32,100, 66,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,116, 32, 41, 32, 10,123, 10, 9,118,101, 99, 50, + 32, 83, 84,108,108, 32, 61, 32,116,101,120, 99,111, 46,120,121, 59, 10, 9,118,101, 99, 50, 32, 83, 84,108,114, 32, 61, 32,116, +101,120, 99,111, 46,120,121, 32, 43, 32,100, 70,100,120, 40,116,101,120, 99,111, 46,120,121, 41, 32, 59, 10, 9,118,101, 99, 50, + 32, 83, 84,117,108, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 43, 32,100, 70,100,121, 40,116,101,120, 99,111, 46,120,121, + 41, 32, 59, 10, 9, 10, 9,102,108,111, 97,116, 32, 72,108,108, 44, 72,108,114, 44, 72,117,108, 59, 10, 9,114,103, 98,116,111, + 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,108,108, 41, 44, 32, 72,108,108, 32, 41, 59, + 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,108,114, 41, 44, + 32, 72,108,114, 32, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, + 32, 83, 84,117,108, 41, 44, 32, 72,117,108, 32, 41, 59, 10, 9, 10, 9,100, 66,115, 32, 61, 32,104, 83, 99, 97,108,101, 32, 42, + 32, 40, 72,108,114, 32, 45, 32, 72,108,108, 41, 59, 10, 9,100, 66,116, 32, 61, 32,104, 83, 99, 97,108,101, 32, 42, 32, 40, 72, +117,108, 32, 45, 32, 72,108,108, 41, 59, 10,125, 10, 10, 35,105,102,100,101,102, 32, 66, 85, 77, 80, 95, 66, 73, 67, 85, 66, 73, + 67, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117,109,112, 95, 98,105, 99,117, 98,105, 99, 40, 32,118,101, 99, 51, 32, +116,101,120, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,102,108,111, 97,116, 32,104, 83, 99, 97, +108,101, 44, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,111,117,116, 32,102,108, +111, 97,116, 32,100, 66,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,116, 32, 41, 32, 10,123, 10, 9,102,108,111, + 97,116, 32, 72,108, 59, 10, 9,102,108,111, 97,116, 32, 72,114, 59, 10, 9,102,108,111, 97,116, 32, 72,100, 59, 10, 9,102,108, +111, 97,116, 32, 72,117, 59, 10, 9, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,120, 32, 61, 32,100, 70,100,120, 40,116,101,120, + 99,111, 46,120,121, 41, 59, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,121, 32, 61, 32,100, 70,100,121, 40,116,101,120, 99,111, + 46,120,121, 41, 59, 10, 32, 10, 9,118,101, 99, 50, 32, 83, 84,108, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 45, 32, 48, + 46, 53, 32, 42, 32, 84,101,120, 68,120, 32, 59, 10, 9,118,101, 99, 50, 32, 83, 84,114, 32, 61, 32,116,101,120, 99,111, 46,120, +121, 32, 43, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,120, 32, 59, 10, 9,118,101, 99, 50, 32, 83, 84,100, 32, 61, 32,116,101, +120, 99,111, 46,120,121, 32, 45, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,121, 32, 59, 10, 9,118,101, 99, 50, 32, 83, 84,117, + 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 43, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,121, 32, 59, 10, 9, 10, 9,114, +103, 98,116,111, 98,119, 40,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,108, 41, 44, 32, 72,108, 41, 59, + 10, 9,114,103, 98,116,111, 98,119, 40,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,114, 41, 44, 32, 72, +114, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,100, 41, + 44, 32, 72,100, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, + 84,117, 41, 44, 32, 72,117, 41, 59, 10, 9, 10, 9,118,101, 99, 50, 32,100, 72,100,120,121, 32, 61, 32,118,101, 99, 50, 40, 72, +114, 32, 45, 32, 72,108, 44, 32, 72,117, 32, 45, 32, 72,100, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 66,108,101,110,100, 32, + 61, 32, 99,108, 97,109,112, 40, 49, 46, 48, 45,116,101,120,116,117,114,101, 81,117,101,114,121, 76, 79, 68, 40,105,109, 97, 44, + 32,116,101,120, 99,111, 46,120,121, 41, 46,120, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,105,102, 40,102, 66,108, +101,110,100, 33, 61, 48, 46, 48, 41, 10, 9,123, 10, 9, 9, 47, 47, 32,116,104,101, 32,100,101,114,105,118, 97,116,105,118,101, + 32,111,102, 32,116,104,101, 32, 98,105, 99,117, 98,105, 99, 32,115, 97,109,112,108,105,110,103, 32,111,102, 32,108,101,118,101, +108, 32, 48, 10, 9, 9,105,118,101, 99, 50, 32,118, 68,105,109, 59, 10, 9, 9,118, 68,105,109, 32, 61, 32,116,101,120,116,117, +114,101, 83,105,122,101, 40,105,109, 97, 44, 32, 48, 41, 59, 10, 10, 9, 9, 47, 47, 32,116, 97,107,105,110,103, 32,116,104,101, + 32,102,114, 97, 99,116, 32,112, 97,114,116, 32,111,102, 32,116,104,101, 32,116,101,120,116,117,114,101, 32, 99,111,111,114,100, +105,110, 97,116,101, 32,105,115, 32, 97, 32,104, 97,114,100, 99,111,100,101,100, 32,119,114, 97,112, 32,109,111,100,101, 46, 10, + 9, 9, 47, 47, 32,116,104,105,115, 32,105,115, 32, 97, 99, 99,101,112,116, 97, 98,108,101, 32, 97,115, 32,116,101,120,116,117, +114,101,115, 32,117,115,101, 32,119,114, 97,112, 32,109,111,100,101, 32,101,120, 99,108,117,115,105,118,101,108,121, 32,105,110, + 32, 51, 68, 32,118,105,101,119, 32,101,108,115,101,119,104,101,114,101, 32,105,110, 32, 98,108,101,110,100,101,114, 46, 32, 10, + 9, 9, 47, 47, 32,116,104,105,115, 32,105,115, 32,100,111,110,101, 32,115,111, 32,116,104, 97,116, 32,119,101, 32, 99, 97,110, + 32,115,116,105,108,108, 32,103,101,116, 32, 97, 32,118, 97,108,105,100, 32,116,101,120,101,108, 32,119,105,116,104, 32,117,118, +115, 32,111,117,116,115,105,100,101, 32,116,104,101, 32, 48, 44, 49, 32,114, 97,110,103,101, 10, 9, 9, 47, 47, 32, 98,121, 32, +116,101,120,101,108, 70,101,116, 99,104, 32, 98,101,108,111,119, 44, 32, 97,115, 32, 99,111,111,114,100,105,110, 97,116,101,115, + 32, 97,114,101, 32, 99,108, 97,109,112,101,100, 32,119,104,101,110, 32,117,115,105,110,103, 32,116,104,105,115, 32,102,117,110, + 99,116,105,111,110, 46, 10, 9, 9,118,101, 99, 50, 32,102, 84,101,120, 76,111, 99, 32, 61, 32,118, 68,105,109, 42,102,114, 97, + 99,116, 40,116,101,120, 99,111, 46,120,121, 41, 32, 45, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 32, 48, 46, 53, 41, 59, 10, 9, + 9,105,118,101, 99, 50, 32,105, 84,101,120, 76,111, 99, 32, 61, 32,105,118,101, 99, 50, 40,102,108,111,111,114, 40,102, 84,101, +120, 76,111, 99, 41, 41, 59, 10, 9, 9,118,101, 99, 50, 32,116, 32, 61, 32, 99,108, 97,109,112, 40,102, 84,101,120, 76,111, 99, + 32, 45, 32,105, 84,101,120, 76,111, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 9, 9, 47, 47, 32,115, 97,116, 32,106, +117,115,116, 32,116,111, 32, 98,101, 32,112,101,100, 97,110,116,105, 99, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 10, 32, 42, 32, 84,104,105,115, 32, 98,108,111, 99,107, - 32,119,105,108,108, 32,114,101,112,108, 97, 99,101, 32,116,104,101, 32,111,110,101, 32, 98,101,108,111,119, 32,119,104,101,110, - 32,111,110,101, 32, 99,104, 97,110,110,101,108, 32,116,101,120,116,117,114,101,115, 32, 97,114,101, 32,112,114,111,112,101,114, -108,121, 32,115,117,112,112,111,114,116,101,100, 46, 32, 42, 10, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 10, 32, 42, 32, 84,104,105,115, 32, 98,108,111, 99,107, 32,119, +105,108,108, 32,114,101,112,108, 97, 99,101, 32,116,104,101, 32,111,110,101, 32, 98,101,108,111,119, 32,119,104,101,110, 32,111, +110,101, 32, 99,104, 97,110,110,101,108, 32,116,101,120,116,117,114,101,115, 32, 97,114,101, 32,112,114,111,112,101,114,108,121, + 32,115,117,112,112,111,114,116,101,100, 46, 32, 42, 10, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 10, 9, 9,118,101, 99, 52, 32,118, 83, 97,109,112,108,101,115, 85, 76, 32, 61, - 32,116,101,120,116,117,114,101, 71, 97,116,104,101,114, 40,105,109, 97, 44, 32, 40,105, 84,101,120, 76,111, 99, 43,105,118,101, - 99, 50, 40, 45, 49, 44, 45, 49, 41, 32, 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 48, 46, 53, 41, 41, 47,118, 68,105,109, 32, - 41, 59, 10, 9, 9,118,101, 99, 52, 32,118, 83, 97,109,112,108,101,115, 85, 82, 32, 61, 32,116,101,120,116,117,114,101, 71, 97, -116,104,101,114, 40,105,109, 97, 44, 32, 40,105, 84,101,120, 76,111, 99, 43,105,118,101, 99, 50, 40, 49, 44, 45, 49, 41, 32, 43, - 32,118,101, 99, 50, 40, 48, 46, 53, 44, 48, 46, 53, 41, 41, 47,118, 68,105,109, 32, 41, 59, 10, 9, 9,118,101, 99, 52, 32,118, - 83, 97,109,112,108,101,115, 76, 76, 32, 61, 32,116,101,120,116,117,114,101, 71, 97,116,104,101,114, 40,105,109, 97, 44, 32, 40, -105, 84,101,120, 76,111, 99, 43,105,118,101, 99, 50, 40, 45, 49, 44, 49, 41, 32, 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 48, - 46, 53, 41, 41, 47,118, 68,105,109, 32, 41, 59, 10, 9, 9,118,101, 99, 52, 32,118, 83, 97,109,112,108,101,115, 76, 82, 32, 61, - 32,116,101,120,116,117,114,101, 71, 97,116,104,101,114, 40,105,109, 97, 44, 32, 40,105, 84,101,120, 76,111, 99, 43,105,118,101, - 99, 50, 40, 49, 44, 49, 41, 32, 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 48, 46, 53, 41, 41, 47,118, 68,105,109, 32, 41, 59, - 10, 10, 9, 9,109, 97,116, 52, 32, 72, 32, 61, 32,109, 97,116, 52, 40,118, 83, 97,109,112,108,101,115, 85, 76, 46,119, 44, 32, -118, 83, 97,109,112,108,101,115, 85, 76, 46,120, 44, 32,118, 83, 97,109,112,108,101,115, 76, 76, 46,119, 44, 32,118, 83, 97,109, -112,108,101,115, 76, 76, 46,120, 44, 10, 9, 9, 9, 9, 9,118, 83, 97,109,112,108,101,115, 85, 76, 46,122, 44, 32,118, 83, 97, -109,112,108,101,115, 85, 76, 46,121, 44, 32,118, 83, 97,109,112,108,101,115, 76, 76, 46,122, 44, 32,118, 83, 97,109,112,108,101, -115, 76, 76, 46,121, 44, 10, 9, 9, 9, 9, 9,118, 83, 97,109,112,108,101,115, 85, 82, 46,119, 44, 32,118, 83, 97,109,112,108, -101,115, 85, 82, 46,120, 44, 32,118, 83, 97,109,112,108,101,115, 76, 82, 46,119, 44, 32,118, 83, 97,109,112,108,101,115, 76, 82, - 46,120, 44, 10, 9, 9, 9, 9, 9,118, 83, 97,109,112,108,101,115, 85, 82, 46,122, 44, 32,118, 83, 97,109,112,108,101,115, 85, - 82, 46,121, 44, 32,118, 83, 97,109,112,108,101,115, 76, 82, 46,122, 44, 32,118, 83, 97,109,112,108,101,115, 76, 82, 46,121, 41, - 59, 10, 42, 47, 9, 10, 9, 9,105,118,101, 99, 50, 32,105, 84,101,120, 76,111, 99, 77,111,100, 32, 61, 32,105, 84,101,120, 76, -111, 99, 32, 43, 32,105,118,101, 99, 50, 40, 45, 49, 44, 32, 45, 49, 41, 59, 10, 10, 9, 9,109, 97,116, 52, 32, 72, 59, 10, 9, - 9, 10, 9, 9,102,111,114, 40,105,110,116, 32,105, 32, 61, 32, 48, 59, 32,105, 32, 60, 32, 52, 59, 32,105, 43, 43, 41,123, 10, - 9, 9, 9,102,111,114, 40,105,110,116, 32,106, 32, 61, 32, 48, 59, 32,106, 32, 60, 32, 52, 59, 32,106, 43, 43, 41,123, 10, 9, - 9, 9, 9,105,118,101, 99, 50, 32,105, 84,101,120, 84,109,112, 32, 61, 32,105, 84,101,120, 76,111, 99, 77,111,100, 32, 43, 32, -105,118,101, 99, 50, 40,105, 44,106, 41, 59, 10, 9, 9, 9, 9, 10, 9, 9, 9, 9, 47, 47, 32,119,114, 97,112, 32,116,101,120, -116,117,114,101, 32, 99,111,111,114,100,105,110, 97,116,101,115, 32,109, 97,110,117, 97,108,108,121, 32,102,111,114, 32,116,101, -120,101,108, 70,101,116, 99,104, 32,116,111, 32,119,111,114,107, 32,111,110, 32,117,118,115, 32,111,105,116,115,105,100,101, 32, -116,104,101, 32, 48, 44, 49, 32,114, 97,110,103,101, 46, 10, 9, 9, 9, 9, 47, 47, 32,116,104,105,115, 32,105,115, 32,103,117, - 97,114, 97,110,116,101,101,100, 32,116,111, 32,119,111,114,107, 32,115,105,110, 99,101, 32,119,101, 32,116, 97,107,101, 32,116, -104,101, 32,102,114, 97, 99,116,105,111,110, 97,108, 32,112, 97,114,116, 32,111,102, 32,116,104,101, 32,117,118, 32, 97, 98,111, -118,101, 46, 10, 9, 9, 9, 9,105, 84,101,120, 84,109,112, 46,120, 32, 61, 32, 40,105, 84,101,120, 84,109,112, 46,120, 32, 60, - 32, 48, 41, 63, 32,105, 84,101,120, 84,109,112, 46,120, 32, 43, 32,118, 68,105,109, 46,120, 32, 58, 32, 40, 40,105, 84,101,120, - 84,109,112, 46,120, 32, 62, 61, 32,118, 68,105,109, 46,120, 41, 63, 32,105, 84,101,120, 84,109,112, 46,120, 32, 45, 32,118, 68, -105,109, 46,120, 32, 58, 32,105, 84,101,120, 84,109,112, 46,120, 41, 59, 10, 9, 9, 9, 9,105, 84,101,120, 84,109,112, 46,121, - 32, 61, 32, 40,105, 84,101,120, 84,109,112, 46,121, 32, 60, 32, 48, 41, 63, 32,105, 84,101,120, 84,109,112, 46,121, 32, 43, 32, -118, 68,105,109, 46,121, 32, 58, 32, 40, 40,105, 84,101,120, 84,109,112, 46,121, 32, 62, 61, 32,118, 68,105,109, 46,121, 41, 63, - 32,105, 84,101,120, 84,109,112, 46,121, 32, 45, 32,118, 68,105,109, 46,121, 32, 58, 32,105, 84,101,120, 84,109,112, 46,121, 41, - 59, 10, 10, 9, 9, 9, 9,114,103, 98,116,111, 98,119, 40,116,101,120,101,108, 70,101,116, 99,104, 40,105,109, 97, 44, 32,105, - 84,101,120, 84,109,112, 44, 32, 48, 41, 44, 32, 72, 91,105, 93, 91,106, 93, 41, 59, 10, 9, 9, 9,125, 10, 9, 9,125, 10, 9, - 9, 10, 9, 9,102,108,111, 97,116, 32,120, 32, 61, 32,116, 46,120, 44, 32,121, 32, 61, 32,116, 46,121, 59, 10, 9, 9,102,108, -111, 97,116, 32,120, 50, 32, 61, 32,120, 32, 42, 32,120, 44, 32,120, 51, 32, 61, 32,120, 50, 32, 42, 32,120, 44, 32,121, 50, 32, - 61, 32,121, 32, 42, 32,121, 44, 32,121, 51, 32, 61, 32,121, 50, 32, 42, 32,121, 59, 10, 10, 9, 9,118,101, 99, 52, 32, 88, 32, - 61, 32,118,101, 99, 52, 40, 45, 48, 46, 53, 42, 40,120, 51, 43,120, 41, 43,120, 50, 44, 9, 9, 49, 46, 53, 42,120, 51, 45, 50, - 46, 53, 42,120, 50, 43, 49, 44, 9, 45, 49, 46, 53, 42,120, 51, 43, 50, 42,120, 50, 43, 48, 46, 53, 42,120, 44, 9, 9, 48, 46, - 53, 42, 40,120, 51, 45,120, 50, 41, 41, 59, 10, 9, 9,118,101, 99, 52, 32, 89, 32, 61, 32,118,101, 99, 52, 40, 45, 48, 46, 53, - 42, 40,121, 51, 43,121, 41, 43,121, 50, 44, 9, 9, 49, 46, 53, 42,121, 51, 45, 50, 46, 53, 42,121, 50, 43, 49, 44, 9, 45, 49, - 46, 53, 42,121, 51, 43, 50, 42,121, 50, 43, 48, 46, 53, 42,121, 44, 9, 9, 48, 46, 53, 42, 40,121, 51, 45,121, 50, 41, 41, 59, - 10, 9, 9,118,101, 99, 52, 32,100, 88, 32, 61, 32,118,101, 99, 52, 40, 45, 49, 46, 53, 42,120, 50, 43, 50, 42,120, 45, 48, 46, - 53, 44, 9, 9, 52, 46, 53, 42,120, 50, 45, 53, 42,120, 44, 9, 9, 9, 45, 52, 46, 53, 42,120, 50, 43, 52, 42,120, 43, 48, 46, - 53, 44, 9, 9, 49, 46, 53, 42,120, 50, 45,120, 41, 59, 10, 9, 9,118,101, 99, 52, 32,100, 89, 32, 61, 32,118,101, 99, 52, 40, - 45, 49, 46, 53, 42,121, 50, 43, 50, 42,121, 45, 48, 46, 53, 44, 9, 9, 52, 46, 53, 42,121, 50, 45, 53, 42,121, 44, 9, 9, 9, - 45, 52, 46, 53, 42,121, 50, 43, 52, 42,121, 43, 48, 46, 53, 44, 9, 9, 49, 46, 53, 42,121, 50, 45,121, 41, 59, 10, 9, 10, 9, - 9, 47, 47, 32, 99,111,109,112,108,101,116,101, 32,100,101,114,105,118, 97,116,105,118,101, 32,105,110, 32,110,111,114,109, 97, -108,105,122,101,100, 32, 99,111,111,114,100,105,110, 97,116,101,115, 32, 40,109,117,108, 32, 98,121, 32,118, 68,105,109, 41, 10, - 9, 9,118,101, 99, 50, 32,100, 72,100, 83, 84, 32, 61, 32,118, 68,105,109, 32, 42, 32,118,101, 99, 50, 40,100,111,116, 40, 89, - 44, 32, 72, 32, 42, 32,100, 88, 41, 44, 32,100,111,116, 40,100, 89, 44, 32, 72, 32, 42, 32, 88, 41, 41, 59, 10, 10, 9, 9, 47, - 47, 32,116,114, 97,110,115,102,111,114,109, 32,100,101,114,105,118, 97,116,105,118,101, 32,116,111, 32,115, 99,114,101,101,110, - 45,115,112, 97, 99,101, 10, 9, 9,118,101, 99, 50, 32,100, 72,100,120,121, 95, 98,105, 99,117, 98,105, 99, 32, 61, 32,118,101, - 99, 50, 40, 32,100, 72,100, 83, 84, 46,120, 32, 42, 32, 84,101,120, 68,120, 46,120, 32, 43, 32,100, 72,100, 83, 84, 46,121, 32, - 42, 32, 84,101,120, 68,120, 46,121, 44, 10, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32,100, 72,100, 83, 84, 46,120, 32, 42, 32, - 84,101,120, 68,121, 46,120, 32, 43, 32,100, 72,100, 83, 84, 46,121, 32, 42, 32, 84,101,120, 68,121, 46,121, 32, 41, 59, 10, 10, - 9, 9, 47, 47, 32, 98,108,101,110,100, 32, 98,101,116,119,101,101,110, 32,116,104,101, 32,116,119,111, 10, 9, 9,100, 72,100, -120,121, 32, 61, 32,100, 72,100,120,121, 42, 40, 49, 45,102, 66,108,101,110,100, 41, 32, 43, 32,100, 72,100,120,121, 95, 98,105, - 99,117, 98,105, 99, 42,102, 66,108,101,110,100, 59, 10, 9,125, 10, 10, 9,100, 66,115, 32, 61, 32,104, 83, 99, 97,108,101, 32, - 42, 32,100, 72,100,120,121, 46,120, 59, 10, 9,100, 66,116, 32, 61, 32,104, 83, 99, 97,108,101, 32, 42, 32,100, 72,100,120,121, - 46,121, 59, 10,125, 10, 10, 35,101,110,100,105,102, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117,109,112, 95,116, 97, -112, 53, 40, 32,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,102, -108,111, 97,116, 32,104, 83, 99, 97,108,101, 44, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,116, 32, - 41, 32, 10,123, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,120, 32, 61, 32,100, 70,100,120, 40,116,101,120, 99,111, 46,120,121, - 41, 59, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,121, 32, 61, 32,100, 70,100,121, 40,116,101,120, 99,111, 46,120,121, 41, 59, - 10, 10, 9,118,101, 99, 50, 32, 83, 84, 99, 32, 61, 32,116,101,120, 99,111, 46,120,121, 59, 10, 9,118,101, 99, 50, 32, 83, 84, -108, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 45, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,120, 32, 59, 10, 9,118,101, - 99, 50, 32, 83, 84,114, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 43, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,120, 32, - 59, 10, 9,118,101, 99, 50, 32, 83, 84,100, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 45, 32, 48, 46, 53, 32, 42, 32, 84, -101,120, 68,121, 32, 59, 10, 9,118,101, 99, 50, 32, 83, 84,117, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 43, 32, 48, 46, - 53, 32, 42, 32, 84,101,120, 68,121, 32, 59, 10, 9, 10, 9,102,108,111, 97,116, 32, 72, 99, 44, 72,108, 44, 72,114, 44, 72,100, - 44, 72,117, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84, - 99, 41, 44, 32, 72, 99, 32, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, - 97, 44, 32, 83, 84,108, 41, 44, 32, 72,108, 32, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, - 50, 68, 40,105,109, 97, 44, 32, 83, 84,114, 41, 44, 32, 72,114, 32, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101, -120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,100, 41, 44, 32, 72,100, 32, 41, 59, 10, 9,114,103, 98,116,111, 98, -119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,117, 41, 44, 32, 72,117, 32, 41, 59, 10, 9, 10, - 9,100, 66,115, 32, 61, 32,104, 83, 99, 97,108,101, 32, 42, 32, 40, 72,114, 32, 45, 32, 72,108, 41, 59, 10, 9,100, 66,116, 32, - 61, 32,104, 83, 99, 97,108,101, 32, 42, 32, 40, 72,117, 32, 45, 32, 72,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95, 98,117,109,112, 95,100,101,114,105,118, 40, 32,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,115, 97,109,112,108, -101,114, 50, 68, 32,105,109, 97, 44, 32,102,108,111, 97,116, 32,105,109, 97, 95,120, 44, 32,102,108,111, 97,116, 32,105,109, 97, - 95,121, 44, 32,102,108,111, 97,116, 32,104, 83, 99, 97,108,101, 44, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,115, 44, 32,111,117,116, 32,102,108,111, 97,116, - 32,100, 66,116, 32, 41, 32, 10,123, 10, 9,102,108,111, 97,116, 32,115, 32, 61, 32, 49, 46, 48, 59, 9, 9, 47, 47, 32,110,101, -103, 97,116,101, 32,116,104,105,115, 32,105,102, 32,102,108,105,112,112,101,100, 32,116,101,120,116,117,114,101, 32, 99,111,111, -114,100,105,110, 97,116,101, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,120, 32, 61, 32,100, 70,100,120, 40,116,101,120, 99,111, - 46,120,121, 41, 59, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,121, 32, 61, 32,100, 70,100,121, 40,116,101,120, 99,111, 46,120, -121, 41, 59, 10, 9, 10, 9, 47, 47, 32,116,104,105,115, 32,118, 97,114,105, 97,110,116, 32,117,115,105,110,103, 32, 97, 32,100, -101,114,105,118, 97,116,105,118,101, 32,109, 97,112, 32,105,115, 32,100,101,115, 99,114,105, 98,101,100, 32,104,101,114,101, 10, - 9, 47, 47, 32,104,116,116,112, 58, 47, 47,109,109,105,107,107,101,108,115,101,110, 51,100, 46, 98,108,111,103,115,112,111,116, - 46, 99,111,109, 47, 50, 48, 49, 49, 47, 48, 55, 47,100,101,114,105,118, 97,116,105,118,101, 45,109, 97,112,115, 46,104,116,109, -108, 10, 9,118,101, 99, 50, 32,100,105,109, 32, 61, 32,118,101, 99, 50, 40,105,109, 97, 95,120, 44, 32,105,109, 97, 95,121, 41, - 59, 10, 9,118,101, 99, 50, 32,100, 66,100,117,118, 32, 61, 32,104, 83, 99, 97,108,101, 42,100,105,109, 42, 40, 50, 46, 48, 42, -116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32,116,101,120, 99,111, 46,120,121, 41, 46,120,121, 45, 49, 46, 48, 41, - 59, 10, 9, 10, 9,100, 66,115, 32, 61, 32,100, 66,100,117,118, 46,120, 42, 84,101,120, 68,120, 46,120, 32, 43, 32,115, 42,100, - 66,100,117,118, 46,121, 42, 84,101,120, 68,120, 46,121, 59, 10, 9,100, 66,116, 32, 61, 32,100, 66,100,117,118, 46,120, 42, 84, -101,120, 68,121, 46,120, 32, 43, 32,115, 42,100, 66,100,117,118, 46,121, 42, 84,101,120, 68,121, 46,121, 59, 10,125, 10, 10,118, -111,105,100, 32,109,116,101,120, 95, 98,117,109,112, 95, 97,112,112,108,121, 40, 32,102,108,111, 97,116, 32,102, 68,101,116, 44, - 32,102,108,111, 97,116, 32,100, 66,115, 44, 32,102,108,111, 97,116, 32,100, 66,116, 44, 32,118,101, 99, 51, 32,118, 82, 49, 44, - 32,118,101, 99, 51, 32,118, 82, 50, 44, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 32, - 32,111,117,116, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,111,117,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32,112,101, -114,116,117,114, 98,101,100, 95,110,111,114,109, 32, 41, 32, 10,123, 10, 9,118,101, 99, 51, 32,118, 83,117,114,102, 71,114, 97, -100, 32, 61, 32,115,105,103,110, 40,102, 68,101,116, 41, 32, 42, 32, 40, 32,100, 66,115, 32, 42, 32,118, 82, 49, 32, 43, 32,100, - 66,116, 32, 42, 32,118, 82, 50, 32, 41, 59, 10, 9, 10, 9,118, 78, 97, 99, 99, 95,111,117,116, 32, 61, 32,118, 78, 97, 99, 99, - 95,105,110, 32, 45, 32,118, 83,117,114,102, 71,114, 97,100, 59, 10, 9,112,101,114,116,117,114, 98,101,100, 95,110,111,114,109, - 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 32,118, 78, 97, 99, 99, 95,111,117,116, 32, 41, 59, 10,125, 10, 10,118,111, -105,100, 32,109,116,101,120, 95, 98,117,109,112, 95, 97,112,112,108,121, 95,116,101,120,115,112, 97, 99,101, 40, 32,102,108,111, - 97,116, 32,102, 68,101,116, 44, 32,102,108,111, 97,116, 32,100, 66,115, 44, 32,102,108,111, 97,116, 32,100, 66,116, 44, 32,118, -101, 99, 51, 32,118, 82, 49, 44, 32,118,101, 99, 51, 32,118, 82, 50, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, - 32,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,102,108,111, 97,116, 32,105,109, 97, 95,120, 44, 32,102,108,111, 97,116, 32, -105,109, 97, 95,121, 44, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, -111,117,116, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,111,117,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32,112,101,114, -116,117,114, 98,101,100, 95,110,111,114,109, 32, 41, 32, 10,123, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,120, 32, 61, 32,100, - 70,100,120, 40,116,101,120, 99,111, 46,120,121, 41, 59, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,121, 32, 61, 32,100, 70,100, -121, 40,116,101,120, 99,111, 46,120,121, 41, 59, 10, 10, 9,118,101, 99, 51, 32,118, 83,117,114,102, 71,114, 97,100, 32, 61, 32, -115,105,103,110, 40,102, 68,101,116, 41, 32, 42, 32, 40, 32, 10, 9, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,100, 66,115, - 32, 47, 32,108,101,110,103,116,104, 40, 32,118,101, 99, 50, 40,105,109, 97, 95,120, 42, 84,101,120, 68,120, 46,120, 44, 32,105, -109, 97, 95,121, 42, 84,101,120, 68,120, 46,121, 41, 32, 41, 32, 42, 32,118, 82, 49, 32, 43, 32, 10, 9, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32,100, 66,116, 32, 47, 32,108,101,110,103,116,104, 40, 32,118,101, 99, 50, 40,105,109, 97, 95,120, 42, 84, -101,120, 68,121, 46,120, 44, 32,105,109, 97, 95,121, 42, 84,101,120, 68,121, 46,121, 41, 32, 41, 32, 42, 32,118, 82, 50, 32, 41, - 59, 10, 9, 9, 9, 9, 10, 9,118, 78, 97, 99, 99, 95,111,117,116, 32, 61, 32,118, 78, 97, 99, 99, 95,105,110, 32, 45, 32,118, - 83,117,114,102, 71,114, 97,100, 59, 10, 9,112,101,114,116,117,114, 98,101,100, 95,110,111,114,109, 32, 61, 32,110,111,114,109, - 97,108,105,122,101, 40, 32,118, 78, 97, 99, 99, 95,111,117,116, 32, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, - 95,110,101,103, 97,116,101, 95,116,101,120,110,111,114,109, 97,108, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111, -117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9,111,117,116,110,111,114,109, 97,108, 32, - 61, 32,118,101, 99, 51, 40, 45,110,111,114,109, 97,108, 46,120, 44, 32, 45,110,111,114,109, 97,108, 46,121, 44, 32,110,111,114, -109, 97,108, 46,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,110,115,112, 97, 99,101, 95,116, 97,110,103, -101,110,116, 40,118,101, 99, 52, 32,116, 97,110,103,101,110,116, 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118, -101, 99, 51, 32,116,101,120,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97, -108, 41, 10,123, 10, 9,118,101, 99, 51, 32, 66, 32, 61, 32,116, 97,110,103,101,110,116, 46,119, 32, 42, 32, 99,114,111,115,115, - 40,110,111,114,109, 97,108, 44, 32,116, 97,110,103,101,110,116, 46,120,121,122, 41, 59, 10, 10, 9,111,117,116,110,111,114,109, - 97,108, 32, 61, 32,116,101,120,110,111,114,109, 97,108, 46,120, 42,116, 97,110,103,101,110,116, 46,120,121,122, 32, 43, 32,116, -101,120,110,111,114,109, 97,108, 46,121, 42, 66, 32, 43, 32,116,101,120,110,111,114,109, 97,108, 46,122, 42,110,111,114,109, 97, -108, 59, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114, -109, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,108,101,110,100, 95,110,111,114,109, 97,108, 40, -102,108,111, 97,116, 32,110,111,114,102, 97, 99, 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118,101, 99, 51, 32, -110,101,119,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, - 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32,110,111,114,102, 97, 99, 41, 42,110,111,114, -109, 97,108, 32, 43, 32,110,111,114,102, 97, 99, 42,110,101,119,110,111,114,109, 97,108, 59, 10, 9,111,117,116,110,111,114,109, - 97,108, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10, 47, 42, - 42, 42, 42, 42, 42, 42, 32, 77, 65, 84, 69, 82, 73, 65, 76, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, - 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,117,110, 95,104,101,109,105, 40,118,101, 99, 51, 32,108, - 97,109,112,118,101, 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100, -105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32, -108, 97,109,112,118,101, 99, 59, 10, 9,100,105,115,116, 32, 61, 32, 49, 46, 48, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, - 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,111,116, -104,101,114, 40,118,101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111, 44, 32,111,117,116, 32,118,101, - 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, - 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, 59, 10, 9, -100,105,115,116, 32, 61, 32,108,101,110,103,116,104, 40,108,118, 41, 59, 10, 9,108,118, 32, 61, 32,110,111,114,109, 97,108,105, -122,101, 40,108,118, 41, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32, -108, 97,109,112, 95,102, 97,108,108,111,102,102, 95,105,110,118,108,105,110,101, 97,114, 40,102,108,111, 97,116, 32,108, 97,109, -112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115, -105,102, 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109, -112,100,105,115,116, 32, 43, 32,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108, -111,102,102, 95,105,110,118,115,113,117, 97,114,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108, -111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9, -118,105,115,105,102, 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,100, -105,115,116, 42,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108,111,102,102, 95, -115,108,105,100,101,114,115, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,108,100, - 49, 44, 32,102,108,111, 97,116, 32,108,100, 50, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108, -111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116,107,119, - 32, 61, 32,108, 97,109,112,100,105,115,116, 42,108, 97,109,112,100,105,115,116, 59, 10, 10, 9,118,105,115,105,102, 97, 99, 32, - 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,108,100, 49, 42,100,105,115,116, 41, - 59, 10, 9,118,105,115,105,102, 97, 99, 32, 42, 61, 32,108, 97,109,112,100,105,115,116,107,119, 47, 40,108, 97,109,112,100,105, -115,116,107,119, 32, 43, 32,108,100, 50, 42,100,105,115,116, 42,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, - 97,109,112, 95,102, 97,108,108,111,102,102, 95, 99,117,114,118,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, - 44, 32,115, 97,109,112,108,101,114, 50, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,102,108,111, 97,116, 32,100,105,115,116, - 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, - 61, 32,116,101,120,116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40,100,105,115,116, 47, -108, 97,109,112,100,105,115,116, 44, 32, 48, 46, 48, 41, 41, 46,120, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95, -118,105,115,105, 98,105,108,105,116,121, 95,115,112,104,101,114,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, - 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 61, 32,108, - 97,109,112,100,105,115,116, 32, 45, 32,100,105,115,116, 59, 10, 10, 9,111,117,116,118,105,115,105,102, 97, 99, 61, 32,118,105, -115,105,102, 97, 99, 42,109, 97,120, 40,116, 44, 32, 48, 46, 48, 41, 47,108, 97,109,112,100,105,115,116, 59, 10,125, 10, 10,118, -111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112,111,116, 95,115,113,117, 97,114,101, 40, -118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,109, 97,116, 52, 32,108, 97,109,112,105,109, 97,116, 44, 32,118,101, 99, - 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112,114, 41, 10,123, 10, 9,105,102, 40,100,111,116, 40, -108,118, 44, 32,108, 97,109,112,118,101, 99, 41, 32, 62, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,118,101, 99, 51, 32,108,118,114, -111,116, 32, 61, 32, 40,108, 97,109,112,105,109, 97,116, 42,118,101, 99, 52, 40,108,118, 44, 32, 48, 46, 48, 41, 41, 46,120,121, -122, 59, 10, 9, 9,102,108,111, 97,116, 32,120, 32, 61, 32,109, 97,120, 40, 97, 98,115, 40,108,118,114,111,116, 46,120, 47,108, -118,114,111,116, 46,122, 41, 44, 32, 97, 98,115, 40,108,118,114,111,116, 46,121, 47,108,118,114,111,116, 46,122, 41, 41, 59, 10, - 10, 9, 9,105,110,112,114, 32, 61, 32, 49, 46, 48, 47,115,113,114,116, 40, 49, 46, 48, 32, 43, 32,120, 42,120, 41, 59, 10, 9, -125, 10, 9,101,108,115,101, 10, 9, 9,105,110,112,114, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97, -109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112,111,116, 95, 99,105,114, 99,108,101, 40,118,101, 99, 51, 32,108, - 97,109,112,118,101, 99, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112,114, 41, - 10,123, 10, 9,105,110,112,114, 32, 61, 32,100,111,116, 40,108,118, 44, 32,108, 97,109,112,118,101, 99, 41, 59, 10,125, 10, 10, -118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112,111,116, 40,102,108,111, 97,116, 32, -115,112,111,116,115,105, 44, 32,102,108,111, 97,116, 32,115,112,111,116, 98,108, 44, 32,102,108,111, 97,116, 32,105,110,112,114, - 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105, -115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 32, 61, 32,115,112,111,116,115,105, 59, 10, 10, 9,105,102, - 40,105,110,112,114, 32, 60, 61, 32,116, 41, 32,123, 10, 9, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32, 48, 46, 48, - 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,116, 32, 61, 32,105,110,112,114, 32, 45, 32,116, 59, 10, 10, 9, 9, - 47, 42, 32,115,111,102,116, 32, 97,114,101, 97, 32, 42, 47, 10, 9, 9,105,102, 40,115,112,111,116, 98,108, 32, 33, 61, 32, 48, - 46, 48, 41, 10, 9, 9, 9,105,110,112,114, 32, 42, 61, 32,115,109,111,111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, - 46, 48, 44, 32,116, 47,115,112,111,116, 98,108, 41, 59, 10, 10, 9, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32,118, -105,115,105,102, 97, 99, 42,105,110,112,114, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115, -105, 98,105,108,105,116,121, 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,111,117,116,118,105,115,105,102, 97, 99, - 32, 61, 32, 40,118,105,115,105,102, 97, 99, 32, 60, 32, 48, 46, 48, 48, 49, 41, 63, 32, 48, 46, 48, 58, 32,118,105,115,105,102, - 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,118,105,101,119, 40,118,101, 99, 51, 32, 99,111, 44, 32, -111,117,116, 32,118,101, 99, 51, 32,118,105,101,119, 41, 10,123, 10, 9, 47, 42, 32,104, 97,110,100,108,101, 32,112,101,114,115, -112,101, 99,116,105,118,101, 47,111,114,116,104,111,103,114, 97,112,104,105, 99, 32, 42, 47, 10, 9,118,105,101,119, 32, 61, 32, - 40,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97,116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, 48, 46, - 48, 41, 63, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 41, 58, 32,118,101, 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, - 44, 32, 45, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,116, 97,110,103,101,110,116, 95,118, - 40,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, 51, 32,116, 97,110,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,110, - 41, 10,123, 10, 9,118,101, 99, 51, 32, 99, 32, 61, 32, 99,114,111,115,115, 40,108,118, 44, 32,116, 97,110,103, 41, 59, 10, 9, -118,101, 99, 51, 32,118,110,111,114, 32, 61, 32, 99,114,111,115,115, 40, 99, 44, 32,116, 97,110,103, 41, 59, 10, 10, 9,118,110, - 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,118,110,111,114, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, -100,101, 95,105,110,112, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, - 97,116, 32,105,110,112, 41, 10,123, 10, 9,105,110,112, 32, 61, 32,100,111,116, 40,118,110, 44, 32,108,118, 41, 59, 10,125, 10, - 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,115, 95,110,111, 95,100,105,102,102,117,115,101, 40,111,117,116, 32,102,108, -111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, -100,101, 95,105,115, 95,104,101,109,105, 40,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, -105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32, 48, 46, 53, 42,105,110,112, 32, 43, 32, 48, 46, 53, 59, 10,125, 10, 10,102,108, -111, 97,116, 32, 97,114,101, 97, 95,108, 97,109,112, 95,101,110,101,114,103,121, 40,109, 97,116, 52, 32, 97,114,101, 97, 44, 32, -118,101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,118,110, 41, 10,123, 10, 9,118,101, 99, 51, 32,118,101, 99, 91, 52, 93, - 44, 32, 99, 91, 52, 93, 59, 10, 9,102,108,111, 97,116, 32,114, 97,100, 91, 52, 93, 44, 32,102, 97, 99, 59, 10, 9, 10, 9,118, -101, 99, 91, 48, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 48, 93, 46,120, -121,122, 41, 59, 10, 9,118,101, 99, 91, 49, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114, -101, 97, 91, 49, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, - 99,111, 32, 45, 32, 97,114,101, 97, 91, 50, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, 91, 51, 93, 32, 61, 32,110,111,114, -109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 51, 93, 46,120,121,122, 41, 59, 10, 10, 9, 99, 91, 48, 93, - 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 48, 93, 44, 32,118,101, 99, 91, 49, - 93, 41, 41, 59, 10, 9, 99, 91, 49, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, - 91, 49, 93, 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9, 99, 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, - 40, 99,114,111,115,115, 40,118,101, 99, 91, 50, 93, 44, 32,118,101, 99, 91, 51, 93, 41, 41, 59, 10, 9, 99, 91, 51, 93, 32, 61, - 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 51, 93, 44, 32,118,101, 99, 91, 48, 93, 41, - 41, 59, 10, 10, 9,114, 97,100, 91, 48, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 48, 93, 44, 32,118, -101, 99, 91, 49, 93, 41, 41, 59, 10, 9,114, 97,100, 91, 49, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, - 49, 93, 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9,114, 97,100, 91, 50, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, - 40,118,101, 99, 91, 50, 93, 44, 32,118,101, 99, 91, 51, 93, 41, 41, 59, 10, 9,114, 97,100, 91, 51, 93, 32, 61, 32, 97, 99,111, -115, 40,100,111,116, 40,118,101, 99, 91, 51, 93, 44, 32,118,101, 99, 91, 48, 93, 41, 41, 59, 10, 10, 9,102, 97, 99, 61, 32, 32, -114, 97,100, 91, 48, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 48, 93, 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, - 91, 49, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 49, 93, 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 50, 93, - 42,100,111,116, 40,118,110, 44, 32, 99, 91, 50, 93, 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 51, 93, 42,100,111, -116, 40,118,110, 44, 32, 99, 91, 51, 93, 41, 59, 10, 10, 9,114,101,116,117,114,110, 32,109, 97,120, 40,102, 97, 99, 44, 32, 48, - 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,110,112, 95, 97,114,101, 97, 40,118,101, 99, 51, - 32,112,111,115,105,116,105,111,110, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109, -112,118,101, 99, 44, 32,118,101, 99, 51, 32,118,110, 44, 32,109, 97,116, 52, 32, 97,114,101, 97, 44, 32,102,108,111, 97,116, 32, - 97,114,101, 97,115,105,122,101, 44, 32,102,108,111, 97,116, 32,107, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112, - 41, 10,123, 10, 9,118,101, 99, 51, 32, 99,111, 32, 61, 32,112,111,115,105,116,105,111,110, 59, 10, 9,118,101, 99, 51, 32,118, -101, 99, 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, 59, 10, 10, 9,105,102, 40,100,111,116, 40,118,101, 99, 44, 32, -108, 97,109,112,118,101, 99, 41, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,105,110,112, 32, 61, 32, 48, 46, 48, 59, 10, 9, -125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,105,110,116,101,110,115, 32, 61, 32, 97,114,101, 97, 95, -108, 97,109,112, 95,101,110,101,114,103,121, 40, 97,114,101, 97, 44, 32, 99,111, 44, 32,118,110, 41, 59, 10, 10, 9, 9,105,110, -112, 32, 61, 32,112,111,119, 40,105,110,116,101,110,115, 42, 97,114,101, 97,115,105,122,101, 44, 32,107, 41, 59, 10, 9,125, 10, -125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105,102,102,117,115,101, 95,111,114,101,110, 95,110, 97,121,101,114, - 40,102,108,111, 97,116, 32,110,108, 44, 32,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32, -118, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, - 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9,102,108,111, - 97,116, 32,110,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,104, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102,108, -111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102, -108,111, 97,116, 32,114,101, 97,108,110,108, 32, 61, 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 10, 9,105,102, 40,114,101, - 97,108,110,108, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108, -115,101, 32,105,102, 40,110,108, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, - 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,118,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,118, 44, - 32,104, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, 97,116, 32, 76,105,116, 95, 65, 32, 61, 32, 97, 99,111,115, 40, -114,101, 97,108,110,108, 41, 59, 10, 9, 9,102,108,111, 97,116, 32, 86,105,101,119, 95, 65, 32, 61, 32, 97, 99,111,115, 40,110, -118, 41, 59, 10, 10, 9, 9,118,101, 99, 51, 32, 76,105,116, 95, 66, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, - 45, 32,114,101, 97,108,110,108, 42,110, 41, 59, 10, 9, 9,118,101, 99, 51, 32, 86,105,101,119, 95, 66, 32, 61, 32,110,111,114, -109, 97,108,105,122,101, 40,118, 32, 45, 32,110,118, 42,110, 41, 59, 10, 10, 9, 9,102,108,111, 97,116, 32,116, 32, 61, 32,109, - 97,120, 40,100,111,116, 40, 76,105,116, 95, 66, 44, 32, 86,105,101,119, 95, 66, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9, -102,108,111, 97,116, 32, 97, 44, 32, 98, 59, 10, 10, 9, 9,105,102, 40, 76,105,116, 95, 65, 32, 62, 32, 86,105,101,119, 95, 65, - 41, 32,123, 10, 9, 9, 9, 97, 32, 61, 32, 76,105,116, 95, 65, 59, 10, 9, 9, 9, 98, 32, 61, 32, 86,105,101,119, 95, 65, 59, - 10, 9, 9,125, 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9, 97, 32, 61, 32, 86,105,101,119, 95, 65, 59, 10, 9, 9, 9, - 98, 32, 61, 32, 76,105,116, 95, 65, 59, 10, 9, 9,125, 10, 10, 9, 9,102,108,111, 97,116, 32, 65, 32, 61, 32, 49, 46, 48, 32, - 45, 32, 40, 48, 46, 53, 42, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 47, 40, 40,114,111,117,103,104, 42,114,111, -117,103,104, 41, 32, 43, 32, 48, 46, 51, 51, 41, 41, 41, 59, 10, 9, 9,102,108,111, 97,116, 32, 66, 32, 61, 32, 48, 46, 52, 53, - 42, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 47, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 32, 43, - 32, 48, 46, 48, 57, 41, 41, 59, 10, 10, 9, 9, 98, 32, 42, 61, 32, 48, 46, 57, 53, 59, 10, 9, 9,105,115, 32, 61, 32,110,108, - 42, 40, 65, 32, 43, 32, 40, 66, 32, 42, 32,116, 32, 42, 32,115,105,110, 40, 97, 41, 32, 42, 32,116, 97,110, 40, 98, 41, 41, 41, - 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105,102,102,117,115,101, 95,116,111,111,110, 40, -118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,115,105, -122,101, 44, 32,102,108,111, 97,116, 32,116,115,109,111,111,116,104, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, - 10,123, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 9,102,108,111, - 97,116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,114,115,108,116, 41, 59, 10, 10, 9,105,102, 40, 97,110,103, 32, 60, 32, -115,105,122,101, 41, 32,105,115, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40, 97,110,103, 32, 62, 32, 40, -115,105,122,101, 32, 43, 32,116,115,109,111,111,116,104, 41, 32,124,124, 32,116,115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, - 48, 41, 32,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,115, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, - 97,110,103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111,111,116,104, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, - 97,100,101, 95,100,105,102,102,117,115,101, 95,109,105,110,110, 97,101,114,116, 40,102,108,111, 97,116, 32,110,108, 44, 32,118, -101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,100, 97,114,107,110,101,115,115, 44, 32,111, -117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,102, 40,110,108, 32, 60, 61, 32, 48, 46, 48, 41, 32,123, 10, - 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,110, -118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9,105,102, 40,100, - 97,114,107,110,101,115,115, 32, 60, 61, 32, 49, 46, 48, 41, 10, 9, 9, 9,105,115, 32, 61, 32,110,108, 42,112,111,119, 40,109, - 97,120, 40,110,118, 42,110,108, 44, 32, 48, 46, 49, 41, 44, 32,100, 97,114,107,110,101,115,115, 32, 45, 32, 49, 46, 48, 41, 59, - 10, 9, 9,101,108,115,101, 10, 9, 9, 9,105,115, 32, 61, 32,110,108, 42,112,111,119, 40, 49, 46, 48, 48, 48, 49, 32, 45, 32, -110,118, 44, 32,100, 97,114,107,110,101,115,115, 32, 45, 32, 49, 46, 48, 41, 59, 10, 9,125, 10,125, 10, 10,102,108,111, 97,116, - 32,102,114,101,115,110,101,108, 95,102, 97, 99, 40,118,101, 99, 51, 32,118,105,101,119, 44, 32,118,101, 99, 51, 32,118,110, 44, - 32,102,108,111, 97,116, 32,103,114, 97,100, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, - 32,116, 49, 44, 32,116, 50, 59, 10, 9,102,108,111, 97,116, 32,102,102, 97, 99, 59, 10, 10, 9,105,102, 40,102, 97, 99, 61, 61, - 48, 46, 48, 41, 32,123, 10, 9, 9,102,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, - 9, 9,116, 49, 61, 32,100,111,116, 40,118,105,101,119, 44, 32,118,110, 41, 59, 10, 9, 9,105,102, 40,116, 49, 62, 48, 46, 48, - 41, 32, 32,116, 50, 61, 32, 49, 46, 48, 43,116, 49, 59, 10, 9, 9,101,108,115,101, 32,116, 50, 61, 32, 49, 46, 48, 45,116, 49, - 59, 10, 10, 9, 9,116, 50, 61, 32,103,114, 97,100, 32, 43, 32, 40, 49, 46, 48, 45,103,114, 97,100, 41, 42,112,111,119, 40,116, - 50, 44, 32,102, 97, 99, 41, 59, 10, 10, 9, 9,105,102, 40,116, 50, 60, 48, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 48, 46, - 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40,116, 50, 62, 49, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, - 10, 9, 9,101,108,115,101, 32,102,102, 97, 99, 32, 61, 32,116, 50, 59, 10, 9,125, 10, 10, 9,114,101,116,117,114,110, 32,102, -102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105,102,102,117,115,101, 95,102,114,101,115,110, -101,108, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32, -102,108,111, 97,116, 32,102, 97, 99, 95,105, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97, -116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32,102,114,101,115,110,101,108, 95,102, 97, 99, 40,108,118, 44, 32,118,110, - 44, 32,102, 97, 99, 95,105, 44, 32,102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 99,117, 98, -105, 99, 40,102,108,111, 97,116, 32,105,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,105,115, 41, 10,123, 10, - 9,105,102, 40,105,115, 62, 48, 46, 48, 32, 38, 38, 32,105,115, 60, 49, 46, 48, 41, 10, 9, 9,111,117,116,105,115, 61, 32,115, -109,111,111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, 46, 48, 44, 32,105,115, 41, 59, 10, 9,101,108,115,101, 10, 9, - 9,111,117,116,105,115, 61, 32,105,115, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,118,105,115,105,102, 97, - 99, 40,102,108,111, 97,116, 32,105, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,102,108,111, 97,116, 32, -114,101,102,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,105, 41, 10,123, 10, 9, 47, 42,105,102, 40,105, 32, - 62, 32, 48, 46, 48, 41, 42, 47, 10, 9, 9,111,117,116,105, 32, 61, 32,109, 97,120, 40,105, 42,118,105,115,105,102, 97, 99, 42, -114,101,102,108, 44, 32, 48, 46, 48, 41, 59, 10, 9, 47, 42,101,108,115,101, 10, 9, 9,111,117,116,105, 32, 61, 32,105, 59, 42, - 47, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,116, 97,110,103,101,110,116, 95,118, 95,115,112,101, 99, 40,118, -101, 99, 51, 32,116, 97,110,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,110, 41, 10,123, 10, 9,118,110, 32, 61, 32,116, - 97,110,103, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 95,116,111, 95,100,105,102,102,117,115, -101, 40,102,108,111, 97,116, 32,105, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111,108, 44, 32,118,101, 99, 51, 32, 99,111, -108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,105,102, 40,105, 32, 62, 32, 48, 46, - 48, 41, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,105, 42,108, 97,109,112, 99,111,108, 42, 99,111,108, 59, 10, 9,101,108, -115,101, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, - 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,104,101,109,105, 95,115,112,101, 99, 40,118,101, 99, 51, 32, -118,110, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,102,108,111, 97,116, 32,115,112, -101, 99, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111, -117,116, 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,108,118, 32, 43, 61, 32,118,105,101,119, 59, 10, 9,108,118, 32, 61, - 32,110,111,114,109, 97,108,105,122,101, 40,108,118, 41, 59, 10, 10, 9,116, 32, 61, 32,100,111,116, 40,118,110, 44, 32,108,118, - 41, 59, 10, 9,116, 32, 61, 32, 48, 46, 53, 42,116, 32, 43, 32, 48, 46, 53, 59, 10, 10, 9,116, 32, 61, 32,118,105,115,105,102, - 97, 99, 42,115,112,101, 99, 42,112,111,119, 40,116, 44, 32,104, 97,114,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, - 97,100,101, 95,112,104,111,110,103, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118, -101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, - 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32, -118, 41, 59, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, 32,109, 97,120, 40,100,111,116, 40,104, 44, 32,110, 41, 44, - 32, 48, 46, 48, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 32, 61, 32,112,111,119, 40,114,115,108,116, 44, 32,104, 97,114, -100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 99,111,111,107,116,111,114,114, 95,115,112,101, 99, 40, -118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97, -114,100, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, - 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, - 32,100,111,116, 40,110, 44, 32,104, 41, 59, 10, 10, 9,105,102, 40,110,104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,115, -112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, - 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, - 97,116, 32,105, 32, 61, 32,112,111,119, 40,110,104, 44, 32,104, 97,114,100, 41, 59, 10, 10, 9, 9,105, 32, 61, 32,105, 47, 40, - 48, 46, 49, 43,110,118, 41, 59, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32,105, 59, 10, 9,125, 10,125, 10, 10,118,111, -105,100, 32,115,104, 97,100,101, 95, 98,108,105,110,110, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, - 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,101,102,114, 97, 99, 44, 32,102,108,111, 97,116, 32, -115,112,101, 99, 95,112,111,119,101,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, - 10, 9,105,102, 40,114,101,102,114, 97, 99, 32, 60, 32, 49, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, - 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,105,102, 40,115,112,101, 99, 95,112,111,119,101,114, 32, 61, 61, 32, - 48, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, - 32,123, 10, 9, 9,105,102, 40,115,112,101, 99, 95,112,111,119,101,114, 60, 49, 48, 48, 46, 48, 41, 10, 9, 9, 9,115,112,101, - 99, 95,112,111,119,101,114, 61, 32,115,113,114,116, 40, 49, 46, 48, 47,115,112,101, 99, 95,112,111,119,101,114, 41, 59, 10, 9, - 9,101,108,115,101, 10, 9, 9, 9,115,112,101, 99, 95,112,111,119,101,114, 61, 32, 49, 48, 46, 48, 47,115,112,101, 99, 95,112, -111,119,101,114, 59, 10, 10, 9, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, 32, -108, 41, 59, 10, 9, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,100,111,116, 40,110, 44, 32,104, 41, 59, 10, 9, 9,105,102, - 40,110,104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, - 9,125, 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111, -116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 49, 41, 59, 10, 9, 9, 9,102,108,111, 97,116, 32,110,108, 32, 61, 32,100,111, -116, 40,110, 44, 32,108, 41, 59, 10, 9, 9, 9,105,102, 40,110,108, 32, 60, 61, 32, 48, 46, 48, 49, 41, 32,123, 10, 9, 9, 9, - 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9, 9,125, 10, 9, 9, 9,101,108,115,101, 32,123, 10, 9, - 9, 9, 9,102,108,111, 97,116, 32,118,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,118, 44, 32,104, 41, 44, 32, 48, 46, 48, - 49, 41, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 97, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9, 9, 9,102,108,111, 97, -116, 32, 98, 32, 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,118, 41, 47,118,104, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, - 99, 32, 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,108, 41, 47,118,104, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,103, - 32, 61, 32, 48, 46, 48, 59, 10, 10, 9, 9, 9, 9,105,102, 40, 97, 32, 60, 32, 98, 32, 38, 38, 32, 97, 32, 60, 32, 99, 41, 32, -103, 32, 61, 32, 97, 59, 10, 9, 9, 9, 9,101,108,115,101, 32,105,102, 40, 98, 32, 60, 32, 97, 32, 38, 38, 32, 98, 32, 60, 32, - 99, 41, 32,103, 32, 61, 32, 98, 59, 10, 9, 9, 9, 9,101,108,115,101, 32,105,102, 40, 99, 32, 60, 32, 97, 32, 38, 38, 32, 99, - 32, 60, 32, 98, 41, 32,103, 32, 61, 32, 99, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,112, 32, 61, 32,115,113,114,116, - 40, 40, 40,114,101,102,114, 97, 99, 32, 42, 32,114,101,102,114, 97, 99, 41, 43, 40,118,104, 42,118,104, 41, 45, 49, 46, 48, 41, - 41, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,102, 32, 61, 32, 40, 40, 40,112, 45,118,104, 41, 42, 40,112, 45,118,104, 41, - 41, 47, 40, 40,112, 43,118,104, 41, 42, 40,112, 43,118,104, 41, 41, 41, 42, 40, 49, 46, 48, 43, 40, 40, 40, 40,118,104, 42, 40, -112, 43,118,104, 41, 41, 45, 49, 46, 48, 41, 42, 40, 40,118,104, 42, 40,112, 43,118,104, 41, 41, 45, 49, 46, 48, 41, 41, 47, 40, - 40, 40,118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, 46, 48, 41, 42, 40, 40,118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, - 46, 48, 41, 41, 41, 41, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,110,104, 41, - 59, 10, 10, 9, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32,109, 97,120, 40,102, 42,103, 42,101,120,112, 95, 98,108,101, -110,100,101,114, 40, 40, 45, 40, 97,110,103, 42, 97,110,103, 41, 47, 40, 50, 46, 48, 42,115,112,101, 99, 95,112,111,119,101,114, - 42,115,112,101, 99, 95,112,111,119,101,114, 41, 41, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9, 9,125, 10, 9, 9,125, 10, 9, -125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,119, 97,114,100,105,115,111, 95,115,112,101, 99, 40,118,101, 99, - 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,109,115, 44, 32, -111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110, -111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,109, 97,120, - 40,100,111,116, 40,110, 44, 32,104, 41, 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32, -109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,108, - 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,108, 41, 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, - 32, 97,110,103,108,101, 32, 61, 32,116, 97,110, 40, 97, 99,111,115, 40,110,104, 41, 41, 59, 10, 9,102,108,111, 97,116, 32, 97, -108,112,104, 97, 32, 61, 32,109, 97,120, 40,114,109,115, 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, - 99, 61, 32,110,108, 32, 42, 32, 40, 49, 46, 48, 47, 40, 52, 46, 48, 42, 77, 95, 80, 73, 42, 97,108,112,104, 97, 42, 97,108,112, -104, 97, 41, 41, 42, 40,101,120,112, 95, 98,108,101,110,100,101,114, 40, 45, 40, 97,110,103,108,101, 42, 97,110,103,108,101, 41, - 47, 40, 97,108,112,104, 97, 42, 97,108,112,104, 97, 41, 41, 47, 40,115,113,114,116, 40,110,118, 42,110,108, 41, 41, 41, 59, 10, -125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,116,111,111,110, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32, -118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,115,105,122,101, 44, 32,102,108,111, 97, -116, 32,116,115,109,111,111,116,104, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, - 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, - 97,116, 32,114,115,108,116, 32, 61, 32,100,111,116, 40,104, 44, 32,110, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103, 32, - 61, 32, 97, 99,111,115, 40,114,115,108,116, 41, 59, 10, 10, 9,105,102, 40, 97,110,103, 32, 60, 32,115,105,122,101, 41, 32,114, -115,108,116, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40, 97,110,103, 32, 62, 61, 32, 40,115,105,122,101, - 32, 43, 32,116,115,109,111,111,116,104, 41, 32,124,124, 32,116,115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, 48, 41, 32,114, -115,108,116, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,114,115,108,116, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, - 97,110,103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111,111,116,104, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 32, - 61, 32,114,115,108,116, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,115,112,101, 99, 95, 97,114,101, 97, 95, -105,110,112, 40,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 44, 32,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117, -116, 32,102,108,111, 97,116, 32,111,117,116,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99,102, 97, - 99, 32, 61, 32,115,112,101, 99,102, 97, 99, 42,105,110,112, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,115, -112,101, 99, 95,116, 40,102,108,111, 97,116, 32,115,104, 97,100,102, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 44, - 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 44, 32,111, -117,116, 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,116, 32, 61, 32,115,104, 97,100,102, 97, 99, 42,115,112,101, 99, 42, -118,105,115,105,102, 97, 99, 42,115,112,101, 99,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97, -100,100, 95,115,112,101, 99, 40,102,108,111, 97,116, 32,116, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111,108, 44, 32,118, -101, 99, 51, 32,115,112,101, 99, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, 10, - 9,111,117,116, 99,111,108, 32, 61, 32,116, 42,108, 97,109,112, 99,111,108, 42,115,112,101, 99, 99,111,108, 59, 10,125, 10, 10, -118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 40,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99, -111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, - 61, 32, 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 10, 9, 9,118,101, 99, 52, 32,118, 83, 97,109,112,108,101,115, 85, 76, 32, 61, 32,116, +101,120,116,117,114,101, 71, 97,116,104,101,114, 40,105,109, 97, 44, 32, 40,105, 84,101,120, 76,111, 99, 43,105,118,101, 99, 50, + 40, 45, 49, 44, 45, 49, 41, 32, 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 48, 46, 53, 41, 41, 47,118, 68,105,109, 32, 41, 59, + 10, 9, 9,118,101, 99, 52, 32,118, 83, 97,109,112,108,101,115, 85, 82, 32, 61, 32,116,101,120,116,117,114,101, 71, 97,116,104, +101,114, 40,105,109, 97, 44, 32, 40,105, 84,101,120, 76,111, 99, 43,105,118,101, 99, 50, 40, 49, 44, 45, 49, 41, 32, 43, 32,118, +101, 99, 50, 40, 48, 46, 53, 44, 48, 46, 53, 41, 41, 47,118, 68,105,109, 32, 41, 59, 10, 9, 9,118,101, 99, 52, 32,118, 83, 97, +109,112,108,101,115, 76, 76, 32, 61, 32,116,101,120,116,117,114,101, 71, 97,116,104,101,114, 40,105,109, 97, 44, 32, 40,105, 84, +101,120, 76,111, 99, 43,105,118,101, 99, 50, 40, 45, 49, 44, 49, 41, 32, 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 48, 46, 53, + 41, 41, 47,118, 68,105,109, 32, 41, 59, 10, 9, 9,118,101, 99, 52, 32,118, 83, 97,109,112,108,101,115, 76, 82, 32, 61, 32,116, +101,120,116,117,114,101, 71, 97,116,104,101,114, 40,105,109, 97, 44, 32, 40,105, 84,101,120, 76,111, 99, 43,105,118,101, 99, 50, + 40, 49, 44, 49, 41, 32, 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 48, 46, 53, 41, 41, 47,118, 68,105,109, 32, 41, 59, 10, 10, + 9, 9,109, 97,116, 52, 32, 72, 32, 61, 32,109, 97,116, 52, 40,118, 83, 97,109,112,108,101,115, 85, 76, 46,119, 44, 32,118, 83, + 97,109,112,108,101,115, 85, 76, 46,120, 44, 32,118, 83, 97,109,112,108,101,115, 76, 76, 46,119, 44, 32,118, 83, 97,109,112,108, +101,115, 76, 76, 46,120, 44, 10, 9, 9, 9, 9, 9,118, 83, 97,109,112,108,101,115, 85, 76, 46,122, 44, 32,118, 83, 97,109,112, +108,101,115, 85, 76, 46,121, 44, 32,118, 83, 97,109,112,108,101,115, 76, 76, 46,122, 44, 32,118, 83, 97,109,112,108,101,115, 76, + 76, 46,121, 44, 10, 9, 9, 9, 9, 9,118, 83, 97,109,112,108,101,115, 85, 82, 46,119, 44, 32,118, 83, 97,109,112,108,101,115, + 85, 82, 46,120, 44, 32,118, 83, 97,109,112,108,101,115, 76, 82, 46,119, 44, 32,118, 83, 97,109,112,108,101,115, 76, 82, 46,120, + 44, 10, 9, 9, 9, 9, 9,118, 83, 97,109,112,108,101,115, 85, 82, 46,122, 44, 32,118, 83, 97,109,112,108,101,115, 85, 82, 46, +121, 44, 32,118, 83, 97,109,112,108,101,115, 76, 82, 46,122, 44, 32,118, 83, 97,109,112,108,101,115, 76, 82, 46,121, 41, 59, 10, + 42, 47, 9, 10, 9, 9,105,118,101, 99, 50, 32,105, 84,101,120, 76,111, 99, 77,111,100, 32, 61, 32,105, 84,101,120, 76,111, 99, + 32, 43, 32,105,118,101, 99, 50, 40, 45, 49, 44, 32, 45, 49, 41, 59, 10, 10, 9, 9,109, 97,116, 52, 32, 72, 59, 10, 9, 9, 10, + 9, 9,102,111,114, 40,105,110,116, 32,105, 32, 61, 32, 48, 59, 32,105, 32, 60, 32, 52, 59, 32,105, 43, 43, 41,123, 10, 9, 9, + 9,102,111,114, 40,105,110,116, 32,106, 32, 61, 32, 48, 59, 32,106, 32, 60, 32, 52, 59, 32,106, 43, 43, 41,123, 10, 9, 9, 9, + 9,105,118,101, 99, 50, 32,105, 84,101,120, 84,109,112, 32, 61, 32,105, 84,101,120, 76,111, 99, 77,111,100, 32, 43, 32,105,118, +101, 99, 50, 40,105, 44,106, 41, 59, 10, 9, 9, 9, 9, 10, 9, 9, 9, 9, 47, 47, 32,119,114, 97,112, 32,116,101,120,116,117, +114,101, 32, 99,111,111,114,100,105,110, 97,116,101,115, 32,109, 97,110,117, 97,108,108,121, 32,102,111,114, 32,116,101,120,101, +108, 70,101,116, 99,104, 32,116,111, 32,119,111,114,107, 32,111,110, 32,117,118,115, 32,111,105,116,115,105,100,101, 32,116,104, +101, 32, 48, 44, 49, 32,114, 97,110,103,101, 46, 10, 9, 9, 9, 9, 47, 47, 32,116,104,105,115, 32,105,115, 32,103,117, 97,114, + 97,110,116,101,101,100, 32,116,111, 32,119,111,114,107, 32,115,105,110, 99,101, 32,119,101, 32,116, 97,107,101, 32,116,104,101, + 32,102,114, 97, 99,116,105,111,110, 97,108, 32,112, 97,114,116, 32,111,102, 32,116,104,101, 32,117,118, 32, 97, 98,111,118,101, + 46, 10, 9, 9, 9, 9,105, 84,101,120, 84,109,112, 46,120, 32, 61, 32, 40,105, 84,101,120, 84,109,112, 46,120, 32, 60, 32, 48, + 41, 63, 32,105, 84,101,120, 84,109,112, 46,120, 32, 43, 32,118, 68,105,109, 46,120, 32, 58, 32, 40, 40,105, 84,101,120, 84,109, +112, 46,120, 32, 62, 61, 32,118, 68,105,109, 46,120, 41, 63, 32,105, 84,101,120, 84,109,112, 46,120, 32, 45, 32,118, 68,105,109, + 46,120, 32, 58, 32,105, 84,101,120, 84,109,112, 46,120, 41, 59, 10, 9, 9, 9, 9,105, 84,101,120, 84,109,112, 46,121, 32, 61, + 32, 40,105, 84,101,120, 84,109,112, 46,121, 32, 60, 32, 48, 41, 63, 32,105, 84,101,120, 84,109,112, 46,121, 32, 43, 32,118, 68, +105,109, 46,121, 32, 58, 32, 40, 40,105, 84,101,120, 84,109,112, 46,121, 32, 62, 61, 32,118, 68,105,109, 46,121, 41, 63, 32,105, + 84,101,120, 84,109,112, 46,121, 32, 45, 32,118, 68,105,109, 46,121, 32, 58, 32,105, 84,101,120, 84,109,112, 46,121, 41, 59, 10, + 10, 9, 9, 9, 9,114,103, 98,116,111, 98,119, 40,116,101,120,101,108, 70,101,116, 99,104, 40,105,109, 97, 44, 32,105, 84,101, +120, 84,109,112, 44, 32, 48, 41, 44, 32, 72, 91,105, 93, 91,106, 93, 41, 59, 10, 9, 9, 9,125, 10, 9, 9,125, 10, 9, 9, 10, + 9, 9,102,108,111, 97,116, 32,120, 32, 61, 32,116, 46,120, 44, 32,121, 32, 61, 32,116, 46,121, 59, 10, 9, 9,102,108,111, 97, +116, 32,120, 50, 32, 61, 32,120, 32, 42, 32,120, 44, 32,120, 51, 32, 61, 32,120, 50, 32, 42, 32,120, 44, 32,121, 50, 32, 61, 32, +121, 32, 42, 32,121, 44, 32,121, 51, 32, 61, 32,121, 50, 32, 42, 32,121, 59, 10, 10, 9, 9,118,101, 99, 52, 32, 88, 32, 61, 32, +118,101, 99, 52, 40, 45, 48, 46, 53, 42, 40,120, 51, 43,120, 41, 43,120, 50, 44, 9, 9, 49, 46, 53, 42,120, 51, 45, 50, 46, 53, + 42,120, 50, 43, 49, 44, 9, 45, 49, 46, 53, 42,120, 51, 43, 50, 42,120, 50, 43, 48, 46, 53, 42,120, 44, 9, 9, 48, 46, 53, 42, + 40,120, 51, 45,120, 50, 41, 41, 59, 10, 9, 9,118,101, 99, 52, 32, 89, 32, 61, 32,118,101, 99, 52, 40, 45, 48, 46, 53, 42, 40, +121, 51, 43,121, 41, 43,121, 50, 44, 9, 9, 49, 46, 53, 42,121, 51, 45, 50, 46, 53, 42,121, 50, 43, 49, 44, 9, 45, 49, 46, 53, + 42,121, 51, 43, 50, 42,121, 50, 43, 48, 46, 53, 42,121, 44, 9, 9, 48, 46, 53, 42, 40,121, 51, 45,121, 50, 41, 41, 59, 10, 9, + 9,118,101, 99, 52, 32,100, 88, 32, 61, 32,118,101, 99, 52, 40, 45, 49, 46, 53, 42,120, 50, 43, 50, 42,120, 45, 48, 46, 53, 44, + 9, 9, 52, 46, 53, 42,120, 50, 45, 53, 42,120, 44, 9, 9, 9, 45, 52, 46, 53, 42,120, 50, 43, 52, 42,120, 43, 48, 46, 53, 44, + 9, 9, 49, 46, 53, 42,120, 50, 45,120, 41, 59, 10, 9, 9,118,101, 99, 52, 32,100, 89, 32, 61, 32,118,101, 99, 52, 40, 45, 49, + 46, 53, 42,121, 50, 43, 50, 42,121, 45, 48, 46, 53, 44, 9, 9, 52, 46, 53, 42,121, 50, 45, 53, 42,121, 44, 9, 9, 9, 45, 52, + 46, 53, 42,121, 50, 43, 52, 42,121, 43, 48, 46, 53, 44, 9, 9, 49, 46, 53, 42,121, 50, 45,121, 41, 59, 10, 9, 10, 9, 9, 47, + 47, 32, 99,111,109,112,108,101,116,101, 32,100,101,114,105,118, 97,116,105,118,101, 32,105,110, 32,110,111,114,109, 97,108,105, +122,101,100, 32, 99,111,111,114,100,105,110, 97,116,101,115, 32, 40,109,117,108, 32, 98,121, 32,118, 68,105,109, 41, 10, 9, 9, +118,101, 99, 50, 32,100, 72,100, 83, 84, 32, 61, 32,118, 68,105,109, 32, 42, 32,118,101, 99, 50, 40,100,111,116, 40, 89, 44, 32, + 72, 32, 42, 32,100, 88, 41, 44, 32,100,111,116, 40,100, 89, 44, 32, 72, 32, 42, 32, 88, 41, 41, 59, 10, 10, 9, 9, 47, 47, 32, +116,114, 97,110,115,102,111,114,109, 32,100,101,114,105,118, 97,116,105,118,101, 32,116,111, 32,115, 99,114,101,101,110, 45,115, +112, 97, 99,101, 10, 9, 9,118,101, 99, 50, 32,100, 72,100,120,121, 95, 98,105, 99,117, 98,105, 99, 32, 61, 32,118,101, 99, 50, + 40, 32,100, 72,100, 83, 84, 46,120, 32, 42, 32, 84,101,120, 68,120, 46,120, 32, 43, 32,100, 72,100, 83, 84, 46,121, 32, 42, 32, + 84,101,120, 68,120, 46,121, 44, 10, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32,100, 72,100, 83, 84, 46,120, 32, 42, 32, 84,101, +120, 68,121, 46,120, 32, 43, 32,100, 72,100, 83, 84, 46,121, 32, 42, 32, 84,101,120, 68,121, 46,121, 32, 41, 59, 10, 10, 9, 9, + 47, 47, 32, 98,108,101,110,100, 32, 98,101,116,119,101,101,110, 32,116,104,101, 32,116,119,111, 10, 9, 9,100, 72,100,120,121, + 32, 61, 32,100, 72,100,120,121, 42, 40, 49, 45,102, 66,108,101,110,100, 41, 32, 43, 32,100, 72,100,120,121, 95, 98,105, 99,117, + 98,105, 99, 42,102, 66,108,101,110,100, 59, 10, 9,125, 10, 10, 9,100, 66,115, 32, 61, 32,104, 83, 99, 97,108,101, 32, 42, 32, +100, 72,100,120,121, 46,120, 59, 10, 9,100, 66,116, 32, 61, 32,104, 83, 99, 97,108,101, 32, 42, 32,100, 72,100,120,121, 46,121, + 59, 10,125, 10, 10, 35,101,110,100,105,102, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,117,109,112, 95,116, 97,112, 53, + 40, 32,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,102,108,111, + 97,116, 32,104, 83, 99, 97,108,101, 44, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,116, 32, 41, 32, + 10,123, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,120, 32, 61, 32,100, 70,100,120, 40,116,101,120, 99,111, 46,120,121, 41, 59, + 10, 9,118,101, 99, 50, 32, 84,101,120, 68,121, 32, 61, 32,100, 70,100,121, 40,116,101,120, 99,111, 46,120,121, 41, 59, 10, 10, + 9,118,101, 99, 50, 32, 83, 84, 99, 32, 61, 32,116,101,120, 99,111, 46,120,121, 59, 10, 9,118,101, 99, 50, 32, 83, 84,108, 32, + 61, 32,116,101,120, 99,111, 46,120,121, 32, 45, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,120, 32, 59, 10, 9,118,101, 99, 50, + 32, 83, 84,114, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 43, 32, 48, 46, 53, 32, 42, 32, 84,101,120, 68,120, 32, 59, 10, + 9,118,101, 99, 50, 32, 83, 84,100, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 45, 32, 48, 46, 53, 32, 42, 32, 84,101,120, + 68,121, 32, 59, 10, 9,118,101, 99, 50, 32, 83, 84,117, 32, 61, 32,116,101,120, 99,111, 46,120,121, 32, 43, 32, 48, 46, 53, 32, + 42, 32, 84,101,120, 68,121, 32, 59, 10, 9, 10, 9,102,108,111, 97,116, 32, 72, 99, 44, 72,108, 44, 72,114, 44, 72,100, 44, 72, +117, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84, 99, 41, + 44, 32, 72, 99, 32, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, + 32, 83, 84,108, 41, 44, 32, 72,108, 32, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116,117,114,101, 50, 68, + 40,105,109, 97, 44, 32, 83, 84,114, 41, 44, 32, 72,114, 32, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, 32,116,101,120,116, +117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,100, 41, 44, 32, 72,100, 32, 41, 59, 10, 9,114,103, 98,116,111, 98,119, 40, + 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32, 83, 84,117, 41, 44, 32, 72,117, 32, 41, 59, 10, 9, 10, 9,100, + 66,115, 32, 61, 32,104, 83, 99, 97,108,101, 32, 42, 32, 40, 72,114, 32, 45, 32, 72,108, 41, 59, 10, 9,100, 66,116, 32, 61, 32, +104, 83, 99, 97,108,101, 32, 42, 32, 40, 72,117, 32, 45, 32, 72,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95, 98,117,109,112, 95,100,101,114,105,118, 40, 32,118,101, 99, 51, 32,116,101,120, 99,111, 44, 32,115, 97,109,112,108,101,114, + 50, 68, 32,105,109, 97, 44, 32,102,108,111, 97,116, 32,105,109, 97, 95,120, 44, 32,102,108,111, 97,116, 32,105,109, 97, 95,121, + 44, 32,102,108,111, 97,116, 32,104, 83, 99, 97,108,101, 44, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32,111,117,116, 32,102,108,111, 97,116, 32,100, 66,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100, + 66,116, 32, 41, 32, 10,123, 10, 9,102,108,111, 97,116, 32,115, 32, 61, 32, 49, 46, 48, 59, 9, 9, 47, 47, 32,110,101,103, 97, +116,101, 32,116,104,105,115, 32,105,102, 32,102,108,105,112,112,101,100, 32,116,101,120,116,117,114,101, 32, 99,111,111,114,100, +105,110, 97,116,101, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,120, 32, 61, 32,100, 70,100,120, 40,116,101,120, 99,111, 46,120, +121, 41, 59, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,121, 32, 61, 32,100, 70,100,121, 40,116,101,120, 99,111, 46,120,121, 41, + 59, 10, 9, 10, 9, 47, 47, 32,116,104,105,115, 32,118, 97,114,105, 97,110,116, 32,117,115,105,110,103, 32, 97, 32,100,101,114, +105,118, 97,116,105,118,101, 32,109, 97,112, 32,105,115, 32,100,101,115, 99,114,105, 98,101,100, 32,104,101,114,101, 10, 9, 47, + 47, 32,104,116,116,112, 58, 47, 47,109,109,105,107,107,101,108,115,101,110, 51,100, 46, 98,108,111,103,115,112,111,116, 46, 99, +111,109, 47, 50, 48, 49, 49, 47, 48, 55, 47,100,101,114,105,118, 97,116,105,118,101, 45,109, 97,112,115, 46,104,116,109,108, 10, + 9,118,101, 99, 50, 32,100,105,109, 32, 61, 32,118,101, 99, 50, 40,105,109, 97, 95,120, 44, 32,105,109, 97, 95,121, 41, 59, 10, + 9,118,101, 99, 50, 32,100, 66,100,117,118, 32, 61, 32,104, 83, 99, 97,108,101, 42,100,105,109, 42, 40, 50, 46, 48, 42,116,101, +120,116,117,114,101, 50, 68, 40,105,109, 97, 44, 32,116,101,120, 99,111, 46,120,121, 41, 46,120,121, 45, 49, 46, 48, 41, 59, 10, + 9, 10, 9,100, 66,115, 32, 61, 32,100, 66,100,117,118, 46,120, 42, 84,101,120, 68,120, 46,120, 32, 43, 32,115, 42,100, 66,100, +117,118, 46,121, 42, 84,101,120, 68,120, 46,121, 59, 10, 9,100, 66,116, 32, 61, 32,100, 66,100,117,118, 46,120, 42, 84,101,120, + 68,121, 46,120, 32, 43, 32,115, 42,100, 66,100,117,118, 46,121, 42, 84,101,120, 68,121, 46,121, 59, 10,125, 10, 10,118,111,105, +100, 32,109,116,101,120, 95, 98,117,109,112, 95, 97,112,112,108,121, 40, 32,102,108,111, 97,116, 32,102, 68,101,116, 44, 32,102, +108,111, 97,116, 32,100, 66,115, 44, 32,102,108,111, 97,116, 32,100, 66,116, 44, 32,118,101, 99, 51, 32,118, 82, 49, 44, 32,118, +101, 99, 51, 32,118, 82, 50, 44, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 32, 32,111, +117,116, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,111,117,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32,112,101,114,116, +117,114, 98,101,100, 95,110,111,114,109, 32, 41, 32, 10,123, 10, 9,118,101, 99, 51, 32,118, 83,117,114,102, 71,114, 97,100, 32, + 61, 32,115,105,103,110, 40,102, 68,101,116, 41, 32, 42, 32, 40, 32,100, 66,115, 32, 42, 32,118, 82, 49, 32, 43, 32,100, 66,116, + 32, 42, 32,118, 82, 50, 32, 41, 59, 10, 9, 10, 9,118, 78, 97, 99, 99, 95,111,117,116, 32, 61, 32,118, 78, 97, 99, 99, 95,105, +110, 32, 45, 32,118, 83,117,114,102, 71,114, 97,100, 59, 10, 9,112,101,114,116,117,114, 98,101,100, 95,110,111,114,109, 32, 61, + 32,110,111,114,109, 97,108,105,122,101, 40, 32,118, 78, 97, 99, 99, 95,111,117,116, 32, 41, 59, 10,125, 10, 10,118,111,105,100, + 32,109,116,101,120, 95, 98,117,109,112, 95, 97,112,112,108,121, 95,116,101,120,115,112, 97, 99,101, 40, 32,102,108,111, 97,116, + 32,102, 68,101,116, 44, 32,102,108,111, 97,116, 32,100, 66,115, 44, 32,102,108,111, 97,116, 32,100, 66,116, 44, 32,118,101, 99, + 51, 32,118, 82, 49, 44, 32,118,101, 99, 51, 32,118, 82, 50, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,118, +101, 99, 51, 32,116,101,120, 99,111, 44, 32,102,108,111, 97,116, 32,105,109, 97, 95,120, 44, 32,102,108,111, 97,116, 32,105,109, + 97, 95,121, 44, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,105,110, 44, 10, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32,111,117, +116, 32,118,101, 99, 51, 32,118, 78, 97, 99, 99, 95,111,117,116, 44, 32,111,117,116, 32,118,101, 99, 51, 32,112,101,114,116,117, +114, 98,101,100, 95,110,111,114,109, 32, 41, 32, 10,123, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,120, 32, 61, 32,100, 70,100, +120, 40,116,101,120, 99,111, 46,120,121, 41, 59, 10, 9,118,101, 99, 50, 32, 84,101,120, 68,121, 32, 61, 32,100, 70,100,121, 40, +116,101,120, 99,111, 46,120,121, 41, 59, 10, 10, 9,118,101, 99, 51, 32,118, 83,117,114,102, 71,114, 97,100, 32, 61, 32,115,105, +103,110, 40,102, 68,101,116, 41, 32, 42, 32, 40, 32, 10, 9, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,100, 66,115, 32, 47, + 32,108,101,110,103,116,104, 40, 32,118,101, 99, 50, 40,105,109, 97, 95,120, 42, 84,101,120, 68,120, 46,120, 44, 32,105,109, 97, + 95,121, 42, 84,101,120, 68,120, 46,121, 41, 32, 41, 32, 42, 32,118, 82, 49, 32, 43, 32, 10, 9, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32,100, 66,116, 32, 47, 32,108,101,110,103,116,104, 40, 32,118,101, 99, 50, 40,105,109, 97, 95,120, 42, 84,101,120, + 68,121, 46,120, 44, 32,105,109, 97, 95,121, 42, 84,101,120, 68,121, 46,121, 41, 32, 41, 32, 42, 32,118, 82, 50, 32, 41, 59, 10, + 9, 9, 9, 9, 10, 9,118, 78, 97, 99, 99, 95,111,117,116, 32, 61, 32,118, 78, 97, 99, 99, 95,105,110, 32, 45, 32,118, 83,117, +114,102, 71,114, 97,100, 59, 10, 9,112,101,114,116,117,114, 98,101,100, 95,110,111,114,109, 32, 61, 32,110,111,114,109, 97,108, +105,122,101, 40, 32,118, 78, 97, 99, 99, 95,111,117,116, 32, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,110, +101,103, 97,116,101, 95,116,101,120,110,111,114,109, 97,108, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, + 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32, +118,101, 99, 51, 40, 45,110,111,114,109, 97,108, 46,120, 44, 32, 45,110,111,114,109, 97,108, 46,121, 44, 32,110,111,114,109, 97, +108, 46,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,110,115,112, 97, 99,101, 95,116, 97,110,103,101,110, +116, 40,118,101, 99, 52, 32,116, 97,110,103,101,110,116, 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118,101, 99, + 51, 32,116,101,120,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, + 10,123, 10, 9,118,101, 99, 51, 32, 66, 32, 61, 32,116, 97,110,103,101,110,116, 46,119, 32, 42, 32, 99,114,111,115,115, 40,110, +111,114,109, 97,108, 44, 32,116, 97,110,103,101,110,116, 46,120,121,122, 41, 59, 10, 10, 9,111,117,116,110,111,114,109, 97,108, + 32, 61, 32,116,101,120,110,111,114,109, 97,108, 46,120, 42,116, 97,110,103,101,110,116, 46,120,121,122, 32, 43, 32,116,101,120, +110,111,114,109, 97,108, 46,121, 42, 66, 32, 43, 32,116,101,120,110,111,114,109, 97,108, 46,122, 42,110,111,114,109, 97,108, 59, + 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114,109, 97, +108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,108,101,110,100, 95,110,111,114,109, 97,108, 40,102,108, +111, 97,116, 32,110,111,114,102, 97, 99, 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118,101, 99, 51, 32,110,101, +119,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, +111,117,116,110,111,114,109, 97,108, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32,110,111,114,102, 97, 99, 41, 42,110,111,114,109, 97, +108, 32, 43, 32,110,111,114,102, 97, 99, 42,110,101,119,110,111,114,109, 97,108, 59, 10, 9,111,117,116,110,111,114,109, 97,108, + 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, + 42, 42, 42, 42, 32, 77, 65, 84, 69, 82, 73, 65, 76, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, 32,108, + 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,117,110, 95,104,101,109,105, 40,118,101, 99, 51, 32,108, 97,109, +112,118,101, 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100,105,115, +116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32,108, 97, +109,112,118,101, 99, 59, 10, 9,100,105,115,116, 32, 61, 32, 49, 46, 48, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, 49, + 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,111,116,104,101, +114, 40,118,101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, + 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, +105,115,105,102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, 59, 10, 9,100,105, +115,116, 32, 61, 32,108,101,110,103,116,104, 40,108,118, 41, 59, 10, 9,108,118, 32, 61, 32,110,111,114,109, 97,108,105,122,101, + 40,108,118, 41, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97, +109,112, 95,102, 97,108,108,111,102,102, 95,105,110,118,108,105,110,101, 97,114, 40,102,108,111, 97,116, 32,108, 97,109,112,100, +105,115,116, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, + 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100, +105,115,116, 32, 43, 32,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108,111,102, +102, 95,105,110,118,115,113,117, 97,114,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97, +116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,118,105, +115,105,102, 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,100,105,115, +116, 42,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108,111,102,102, 95,115,108, +105,100,101,114,115, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,108,100, 49, 44, + 32,102,108,111, 97,116, 32,108,100, 50, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116,107,119, 32, 61, + 32,108, 97,109,112,100,105,115,116, 42,108, 97,109,112,100,105,115,116, 59, 10, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, +108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,108,100, 49, 42,100,105,115,116, 41, 59, 10, + 9,118,105,115,105,102, 97, 99, 32, 42, 61, 32,108, 97,109,112,100,105,115,116,107,119, 47, 40,108, 97,109,112,100,105,115,116, +107,119, 32, 43, 32,108,100, 50, 42,100,105,115,116, 42,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109, +112, 95,102, 97,108,108,111,102,102, 95, 99,117,114,118,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32, +115, 97,109,112,108,101,114, 50, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, +116,101,120,116,117,114,101, 50, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,118,101, 99, 50, 40,100,105,115,116, 47,108, 97, +109,112,100,105,115,116, 44, 32, 48, 46, 48, 41, 41, 46,120, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105, +115,105, 98,105,108,105,116,121, 95,115,112,104,101,114,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32, +102,108,111, 97,116, 32,100,105,115,116, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 61, 32,108, 97,109, +112,100,105,115,116, 32, 45, 32,100,105,115,116, 59, 10, 10, 9,111,117,116,118,105,115,105,102, 97, 99, 61, 32,118,105,115,105, +102, 97, 99, 42,109, 97,120, 40,116, 44, 32, 48, 46, 48, 41, 47,108, 97,109,112,100,105,115,116, 59, 10,125, 10, 10,118,111,105, +100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112,111,116, 95,115,113,117, 97,114,101, 40,118,101, + 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,109, 97,116, 52, 32,108, 97,109,112,105,109, 97,116, 44, 32,118,101, 99, 51, 32, +108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112,114, 41, 10,123, 10, 9,105,102, 40,100,111,116, 40,108,118, + 44, 32,108, 97,109,112,118,101, 99, 41, 32, 62, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,118,101, 99, 51, 32,108,118,114,111,116, + 32, 61, 32, 40,108, 97,109,112,105,109, 97,116, 42,118,101, 99, 52, 40,108,118, 44, 32, 48, 46, 48, 41, 41, 46,120,121,122, 59, + 10, 9, 9,102,108,111, 97,116, 32,120, 32, 61, 32,109, 97,120, 40, 97, 98,115, 40,108,118,114,111,116, 46,120, 47,108,118,114, +111,116, 46,122, 41, 44, 32, 97, 98,115, 40,108,118,114,111,116, 46,121, 47,108,118,114,111,116, 46,122, 41, 41, 59, 10, 10, 9, + 9,105,110,112,114, 32, 61, 32, 49, 46, 48, 47,115,113,114,116, 40, 49, 46, 48, 32, 43, 32,120, 42,120, 41, 59, 10, 9,125, 10, + 9,101,108,115,101, 10, 9, 9,105,110,112,114, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, + 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112,111,116, 95, 99,105,114, 99,108,101, 40,118,101, 99, 51, 32,108, 97,109, +112,118,101, 99, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112,114, 41, 10,123, + 10, 9,105,110,112,114, 32, 61, 32,100,111,116, 40,108,118, 44, 32,108, 97,109,112,118,101, 99, 41, 59, 10,125, 10, 10,118,111, +105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112,111,116, 40,102,108,111, 97,116, 32,115,112, +111,116,115,105, 44, 32,102,108,111, 97,116, 32,115,112,111,116, 98,108, 44, 32,102,108,111, 97,116, 32,105,110,112,114, 44, 32, +102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105, +102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 32, 61, 32,115,112,111,116,115,105, 59, 10, 10, 9,105,102, 40,105, +110,112,114, 32, 60, 61, 32,116, 41, 32,123, 10, 9, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, + 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,116, 32, 61, 32,105,110,112,114, 32, 45, 32,116, 59, 10, 10, 9, 9, 47, 42, + 32,115,111,102,116, 32, 97,114,101, 97, 32, 42, 47, 10, 9, 9,105,102, 40,115,112,111,116, 98,108, 32, 33, 61, 32, 48, 46, 48, + 41, 10, 9, 9, 9,105,110,112,114, 32, 42, 61, 32,115,109,111,111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, 46, 48, + 44, 32,116, 47,115,112,111,116, 98,108, 41, 59, 10, 10, 9, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32,118,105,115, +105,102, 97, 99, 42,105,110,112,114, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98, +105,108,105,116,121, 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, + 32, 40,118,105,115,105,102, 97, 99, 32, 60, 32, 48, 46, 48, 48, 49, 41, 63, 32, 48, 46, 48, 58, 32,118,105,115,105,102, 97, 99, + 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,118,105,101,119, 40,118,101, 99, 51, 32, 99,111, 44, 32,111,117, +116, 32,118,101, 99, 51, 32,118,105,101,119, 41, 10,123, 10, 9, 47, 42, 32,104, 97,110,100,108,101, 32,112,101,114,115,112,101, + 99,116,105,118,101, 47,111,114,116,104,111,103,114, 97,112,104,105, 99, 32, 42, 47, 10, 9,118,105,101,119, 32, 61, 32, 40,103, +108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97,116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, 48, 46, 48, 41, + 63, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 41, 58, 32,118,101, 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, + 45, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,116, 97,110,103,101,110,116, 95,118, 40,118, +101, 99, 51, 32,108,118, 44, 32,118,101, 99, 51, 32,116, 97,110,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,110, 41, 10, +123, 10, 9,118,101, 99, 51, 32, 99, 32, 61, 32, 99,114,111,115,115, 40,108,118, 44, 32,116, 97,110,103, 41, 59, 10, 9,118,101, + 99, 51, 32,118,110,111,114, 32, 61, 32, 99,114,111,115,115, 40, 99, 44, 32,116, 97,110,103, 41, 59, 10, 10, 9,118,110, 32, 61, + 32, 45,110,111,114,109, 97,108,105,122,101, 40,118,110,111,114, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,105,110,112, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, + 32,105,110,112, 41, 10,123, 10, 9,105,110,112, 32, 61, 32,100,111,116, 40,118,110, 44, 32,108,118, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,115,104, 97,100,101, 95,105,115, 95,110,111, 95,100,105,102,102,117,115,101, 40,111,117,116, 32,102,108,111, 97, +116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,105,115, 95,104,101,109,105, 40,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, + 41, 10,123, 10, 9,105,115, 32, 61, 32, 48, 46, 53, 42,105,110,112, 32, 43, 32, 48, 46, 53, 59, 10,125, 10, 10,102,108,111, 97, +116, 32, 97,114,101, 97, 95,108, 97,109,112, 95,101,110,101,114,103,121, 40,109, 97,116, 52, 32, 97,114,101, 97, 44, 32,118,101, + 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,118,110, 41, 10,123, 10, 9,118,101, 99, 51, 32,118,101, 99, 91, 52, 93, 44, 32, + 99, 91, 52, 93, 59, 10, 9,102,108,111, 97,116, 32,114, 97,100, 91, 52, 93, 44, 32,102, 97, 99, 59, 10, 9, 10, 9,118,101, 99, + 91, 48, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 48, 93, 46,120,121,122, + 41, 59, 10, 9,118,101, 99, 91, 49, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, + 91, 49, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, + 32, 45, 32, 97,114,101, 97, 91, 50, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, 91, 51, 93, 32, 61, 32,110,111,114,109, 97, +108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 51, 93, 46,120,121,122, 41, 59, 10, 10, 9, 99, 91, 48, 93, 32, 61, + 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 48, 93, 44, 32,118,101, 99, 91, 49, 93, 41, + 41, 59, 10, 9, 99, 91, 49, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 49, + 93, 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9, 99, 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99, +114,111,115,115, 40,118,101, 99, 91, 50, 93, 44, 32,118,101, 99, 91, 51, 93, 41, 41, 59, 10, 9, 99, 91, 51, 93, 32, 61, 32,110, +111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 51, 93, 44, 32,118,101, 99, 91, 48, 93, 41, 41, 59, + 10, 10, 9,114, 97,100, 91, 48, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 48, 93, 44, 32,118,101, 99, + 91, 49, 93, 41, 41, 59, 10, 9,114, 97,100, 91, 49, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 49, 93, + 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9,114, 97,100, 91, 50, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118, +101, 99, 91, 50, 93, 44, 32,118,101, 99, 91, 51, 93, 41, 41, 59, 10, 9,114, 97,100, 91, 51, 93, 32, 61, 32, 97, 99,111,115, 40, +100,111,116, 40,118,101, 99, 91, 51, 93, 44, 32,118,101, 99, 91, 48, 93, 41, 41, 59, 10, 10, 9,102, 97, 99, 61, 32, 32,114, 97, +100, 91, 48, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 48, 93, 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 49, + 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 49, 93, 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 50, 93, 42,100, +111,116, 40,118,110, 44, 32, 99, 91, 50, 93, 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 51, 93, 42,100,111,116, 40, +118,110, 44, 32, 99, 91, 51, 93, 41, 59, 10, 10, 9,114,101,116,117,114,110, 32,109, 97,120, 40,102, 97, 99, 44, 32, 48, 46, 48, + 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,110,112, 95, 97,114,101, 97, 40,118,101, 99, 51, 32,112, +111,115,105,116,105,111,110, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109,112,118, +101, 99, 44, 32,118,101, 99, 51, 32,118,110, 44, 32,109, 97,116, 52, 32, 97,114,101, 97, 44, 32,102,108,111, 97,116, 32, 97,114, +101, 97,115,105,122,101, 44, 32,102,108,111, 97,116, 32,107, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112, 41, 10, +123, 10, 9,118,101, 99, 51, 32, 99,111, 32, 61, 32,112,111,115,105,116,105,111,110, 59, 10, 9,118,101, 99, 51, 32,118,101, 99, + 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, 59, 10, 10, 9,105,102, 40,100,111,116, 40,118,101, 99, 44, 32,108, 97, +109,112,118,101, 99, 41, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,105,110,112, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, + 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,105,110,116,101,110,115, 32, 61, 32, 97,114,101, 97, 95,108, 97, +109,112, 95,101,110,101,114,103,121, 40, 97,114,101, 97, 44, 32, 99,111, 44, 32,118,110, 41, 59, 10, 10, 9, 9,105,110,112, 32, + 61, 32,112,111,119, 40,105,110,116,101,110,115, 42, 97,114,101, 97,115,105,122,101, 44, 32,107, 41, 59, 10, 9,125, 10,125, 10, + 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105,102,102,117,115,101, 95,111,114,101,110, 95,110, 97,121,101,114, 40,102, +108,111, 97,116, 32,110,108, 44, 32,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, + 32,102,108,111, 97,116, 32,114,111,117,103,104, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,118, +101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9,102,108,111, 97,116, + 32,110,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,104, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102,108,111, 97, +116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102,108,111, + 97,116, 32,114,101, 97,108,110,108, 32, 61, 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 10, 9,105,102, 40,114,101, 97,108, +110,108, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, + 32,105,102, 40,110,108, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9, +101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,118,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,118, 44, 32,104, + 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, 97,116, 32, 76,105,116, 95, 65, 32, 61, 32, 97, 99,111,115, 40,114,101, + 97,108,110,108, 41, 59, 10, 9, 9,102,108,111, 97,116, 32, 86,105,101,119, 95, 65, 32, 61, 32, 97, 99,111,115, 40,110,118, 41, + 59, 10, 10, 9, 9,118,101, 99, 51, 32, 76,105,116, 95, 66, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 45, 32, +114,101, 97,108,110,108, 42,110, 41, 59, 10, 9, 9,118,101, 99, 51, 32, 86,105,101,119, 95, 66, 32, 61, 32,110,111,114,109, 97, +108,105,122,101, 40,118, 32, 45, 32,110,118, 42,110, 41, 59, 10, 10, 9, 9,102,108,111, 97,116, 32,116, 32, 61, 32,109, 97,120, + 40,100,111,116, 40, 76,105,116, 95, 66, 44, 32, 86,105,101,119, 95, 66, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9,102,108, +111, 97,116, 32, 97, 44, 32, 98, 59, 10, 10, 9, 9,105,102, 40, 76,105,116, 95, 65, 32, 62, 32, 86,105,101,119, 95, 65, 41, 32, +123, 10, 9, 9, 9, 97, 32, 61, 32, 76,105,116, 95, 65, 59, 10, 9, 9, 9, 98, 32, 61, 32, 86,105,101,119, 95, 65, 59, 10, 9, + 9,125, 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9, 97, 32, 61, 32, 86,105,101,119, 95, 65, 59, 10, 9, 9, 9, 98, 32, + 61, 32, 76,105,116, 95, 65, 59, 10, 9, 9,125, 10, 10, 9, 9,102,108,111, 97,116, 32, 65, 32, 61, 32, 49, 46, 48, 32, 45, 32, + 40, 48, 46, 53, 42, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 47, 40, 40,114,111,117,103,104, 42,114,111,117,103, +104, 41, 32, 43, 32, 48, 46, 51, 51, 41, 41, 41, 59, 10, 9, 9,102,108,111, 97,116, 32, 66, 32, 61, 32, 48, 46, 52, 53, 42, 40, + 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 47, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 32, 43, 32, 48, + 46, 48, 57, 41, 41, 59, 10, 10, 9, 9, 98, 32, 42, 61, 32, 48, 46, 57, 53, 59, 10, 9, 9,105,115, 32, 61, 32,110,108, 42, 40, + 65, 32, 43, 32, 40, 66, 32, 42, 32,116, 32, 42, 32,115,105,110, 40, 97, 41, 32, 42, 32,116, 97,110, 40, 98, 41, 41, 41, 59, 10, + 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105,102,102,117,115,101, 95,116,111,111,110, 40,118,101, + 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,115,105,122,101, + 44, 32,102,108,111, 97,116, 32,116,115,109,111,111,116,104, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, + 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 9,102,108,111, 97,116, + 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,114,115,108,116, 41, 59, 10, 10, 9,105,102, 40, 97,110,103, 32, 60, 32,115,105, +122,101, 41, 32,105,115, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40, 97,110,103, 32, 62, 32, 40,115,105, +122,101, 32, 43, 32,116,115,109,111,111,116,104, 41, 32,124,124, 32,116,115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, 48, 41, + 32,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,115, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, 97,110, +103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111,111,116,104, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100, +101, 95,100,105,102,102,117,115,101, 95,109,105,110,110, 97,101,114,116, 40,102,108,111, 97,116, 32,110,108, 44, 32,118,101, 99, + 51, 32,110, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,100, 97,114,107,110,101,115,115, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,102, 40,110,108, 32, 60, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9, +105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,110,118, 32, + 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9,105,102, 40,100, 97,114, +107,110,101,115,115, 32, 60, 61, 32, 49, 46, 48, 41, 10, 9, 9, 9,105,115, 32, 61, 32,110,108, 42,112,111,119, 40,109, 97,120, + 40,110,118, 42,110,108, 44, 32, 48, 46, 49, 41, 44, 32,100, 97,114,107,110,101,115,115, 32, 45, 32, 49, 46, 48, 41, 59, 10, 9, + 9,101,108,115,101, 10, 9, 9, 9,105,115, 32, 61, 32,110,108, 42,112,111,119, 40, 49, 46, 48, 48, 48, 49, 32, 45, 32,110,118, + 44, 32,100, 97,114,107,110,101,115,115, 32, 45, 32, 49, 46, 48, 41, 59, 10, 9,125, 10,125, 10, 10,102,108,111, 97,116, 32,102, +114,101,115,110,101,108, 95,102, 97, 99, 40,118,101, 99, 51, 32,118,105,101,119, 44, 32,118,101, 99, 51, 32,118,110, 44, 32,102, +108,111, 97,116, 32,103,114, 97,100, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, + 49, 44, 32,116, 50, 59, 10, 9,102,108,111, 97,116, 32,102,102, 97, 99, 59, 10, 10, 9,105,102, 40,102, 97, 99, 61, 61, 48, 46, + 48, 41, 32,123, 10, 9, 9,102,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9, +116, 49, 61, 32,100,111,116, 40,118,105,101,119, 44, 32,118,110, 41, 59, 10, 9, 9,105,102, 40,116, 49, 62, 48, 46, 48, 41, 32, + 32,116, 50, 61, 32, 49, 46, 48, 43,116, 49, 59, 10, 9, 9,101,108,115,101, 32,116, 50, 61, 32, 49, 46, 48, 45,116, 49, 59, 10, + 10, 9, 9,116, 50, 61, 32,103,114, 97,100, 32, 43, 32, 40, 49, 46, 48, 45,103,114, 97,100, 41, 42,112,111,119, 40,116, 50, 44, + 32,102, 97, 99, 41, 59, 10, 10, 9, 9,105,102, 40,116, 50, 60, 48, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, + 10, 9, 9,101,108,115,101, 32,105,102, 40,116, 50, 62, 49, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10, 9, + 9,101,108,115,101, 32,102,102, 97, 99, 32, 61, 32,116, 50, 59, 10, 9,125, 10, 10, 9,114,101,116,117,114,110, 32,102,102, 97, + 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105,102,102,117,115,101, 95,102,114,101,115,110,101,108, + 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,102,108, +111, 97,116, 32,102, 97, 99, 95,105, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, +105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32,102,114,101,115,110,101,108, 95,102, 97, 99, 40,108,118, 44, 32,118,110, 44, 32, +102, 97, 99, 95,105, 44, 32,102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 99,117, 98,105, 99, + 40,102,108,111, 97,116, 32,105,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,105,115, 41, 10,123, 10, 9,105, +102, 40,105,115, 62, 48, 46, 48, 32, 38, 38, 32,105,115, 60, 49, 46, 48, 41, 10, 9, 9,111,117,116,105,115, 61, 32,115,109,111, +111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, 46, 48, 44, 32,105,115, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111, +117,116,105,115, 61, 32,105,115, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,118,105,115,105,102, 97, 99, 40, +102,108,111, 97,116, 32,105, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,102,108,111, 97,116, 32,114,101, +102,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,105, 41, 10,123, 10, 9, 47, 42,105,102, 40,105, 32, 62, 32, + 48, 46, 48, 41, 42, 47, 10, 9, 9,111,117,116,105, 32, 61, 32,109, 97,120, 40,105, 42,118,105,115,105,102, 97, 99, 42,114,101, +102,108, 44, 32, 48, 46, 48, 41, 59, 10, 9, 47, 42,101,108,115,101, 10, 9, 9,111,117,116,105, 32, 61, 32,105, 59, 42, 47, 10, +125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,116, 97,110,103,101,110,116, 95,118, 95,115,112,101, 99, 40,118,101, 99, + 51, 32,116, 97,110,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,110, 41, 10,123, 10, 9,118,110, 32, 61, 32,116, 97,110, +103, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 95,116,111, 95,100,105,102,102,117,115,101, 40, +102,108,111, 97,116, 32,105, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111,108, 44, 32,118,101, 99, 51, 32, 99,111,108, 44, + 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,105,102, 40,105, 32, 62, 32, 48, 46, 48, 41, + 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,105, 42,108, 97,109,112, 99,111,108, 42, 99,111,108, 59, 10, 9,101,108,115,101, + 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,104,101,109,105, 95,115,112,101, 99, 40,118,101, 99, 51, 32,118,110, + 44, 32,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, + 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,108,118, 32, 43, 61, 32,118,105,101,119, 59, 10, 9,108,118, 32, 61, 32,110, +111,114,109, 97,108,105,122,101, 40,108,118, 41, 59, 10, 10, 9,116, 32, 61, 32,100,111,116, 40,118,110, 44, 32,108,118, 41, 59, + 10, 9,116, 32, 61, 32, 48, 46, 53, 42,116, 32, 43, 32, 48, 46, 53, 59, 10, 10, 9,116, 32, 61, 32,118,105,115,105,102, 97, 99, + 42,115,112,101, 99, 42,112,111,119, 40,116, 44, 32,104, 97,114,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100, +101, 95,112,104,111,110,103, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, + 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, + 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, + 59, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, 32,109, 97,120, 40,100,111,116, 40,104, 44, 32,110, 41, 44, 32, 48, + 46, 48, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 32, 61, 32,112,111,119, 40,114,115,108,116, 44, 32,104, 97,114,100, 41, + 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 99,111,111,107,116,111,114,114, 95,115,112,101, 99, 40,118,101, + 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, + 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,100, +111,116, 40,110, 44, 32,104, 41, 59, 10, 10, 9,105,102, 40,110,104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, + 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,110, +118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, 97,116, + 32,105, 32, 61, 32,112,111,119, 40,110,104, 44, 32,104, 97,114,100, 41, 59, 10, 10, 9, 9,105, 32, 61, 32,105, 47, 40, 48, 46, + 49, 43,110,118, 41, 59, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32,105, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, + 32,115,104, 97,100,101, 95, 98,108,105,110,110, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, + 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,101,102,114, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112, +101, 99, 95,112,111,119,101,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9, +105,102, 40,114,101,102,114, 97, 99, 32, 60, 32, 49, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, + 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,105,102, 40,115,112,101, 99, 95,112,111,119,101,114, 32, 61, 61, 32, 48, 46, + 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, + 10, 9, 9,105,102, 40,115,112,101, 99, 95,112,111,119,101,114, 60, 49, 48, 48, 46, 48, 41, 10, 9, 9, 9,115,112,101, 99, 95, +112,111,119,101,114, 61, 32,115,113,114,116, 40, 49, 46, 48, 47,115,112,101, 99, 95,112,111,119,101,114, 41, 59, 10, 9, 9,101, +108,115,101, 10, 9, 9, 9,115,112,101, 99, 95,112,111,119,101,114, 61, 32, 49, 48, 46, 48, 47,115,112,101, 99, 95,112,111,119, +101,114, 59, 10, 10, 9, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, 32,108, 41, + 59, 10, 9, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,100,111,116, 40,110, 44, 32,104, 41, 59, 10, 9, 9,105,102, 40,110, +104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,125, + 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40, +110, 44, 32,118, 41, 44, 32, 48, 46, 48, 49, 41, 59, 10, 9, 9, 9,102,108,111, 97,116, 32,110,108, 32, 61, 32,100,111,116, 40, +110, 44, 32,108, 41, 59, 10, 9, 9, 9,105,102, 40,110,108, 32, 60, 61, 32, 48, 46, 48, 49, 41, 32,123, 10, 9, 9, 9, 9,115, +112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9, 9,125, 10, 9, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9, + 9,102,108,111, 97,116, 32,118,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,118, 44, 32,104, 41, 44, 32, 48, 46, 48, 49, 41, + 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 97, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, + 98, 32, 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,118, 41, 47,118,104, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 99, 32, + 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,108, 41, 47,118,104, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,103, 32, 61, + 32, 48, 46, 48, 59, 10, 10, 9, 9, 9, 9,105,102, 40, 97, 32, 60, 32, 98, 32, 38, 38, 32, 97, 32, 60, 32, 99, 41, 32,103, 32, + 61, 32, 97, 59, 10, 9, 9, 9, 9,101,108,115,101, 32,105,102, 40, 98, 32, 60, 32, 97, 32, 38, 38, 32, 98, 32, 60, 32, 99, 41, + 32,103, 32, 61, 32, 98, 59, 10, 9, 9, 9, 9,101,108,115,101, 32,105,102, 40, 99, 32, 60, 32, 97, 32, 38, 38, 32, 99, 32, 60, + 32, 98, 41, 32,103, 32, 61, 32, 99, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,112, 32, 61, 32,115,113,114,116, 40, 40, + 40,114,101,102,114, 97, 99, 32, 42, 32,114,101,102,114, 97, 99, 41, 43, 40,118,104, 42,118,104, 41, 45, 49, 46, 48, 41, 41, 59, + 10, 9, 9, 9, 9,102,108,111, 97,116, 32,102, 32, 61, 32, 40, 40, 40,112, 45,118,104, 41, 42, 40,112, 45,118,104, 41, 41, 47, + 40, 40,112, 43,118,104, 41, 42, 40,112, 43,118,104, 41, 41, 41, 42, 40, 49, 46, 48, 43, 40, 40, 40, 40,118,104, 42, 40,112, 43, +118,104, 41, 41, 45, 49, 46, 48, 41, 42, 40, 40,118,104, 42, 40,112, 43,118,104, 41, 41, 45, 49, 46, 48, 41, 41, 47, 40, 40, 40, +118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, 46, 48, 41, 42, 40, 40,118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, 46, 48, + 41, 41, 41, 41, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,110,104, 41, 59, 10, + 10, 9, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32,109, 97,120, 40,102, 42,103, 42,101,120,112, 95, 98,108,101,110,100, +101,114, 40, 40, 45, 40, 97,110,103, 42, 97,110,103, 41, 47, 40, 50, 46, 48, 42,115,112,101, 99, 95,112,111,119,101,114, 42,115, +112,101, 99, 95,112,111,119,101,114, 41, 41, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9, 9,125, 10, 9, 9,125, 10, 9,125, 10, +125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,119, 97,114,100,105,115,111, 95,115,112,101, 99, 40,118,101, 99, 51, 32, +110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,109,115, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114, +109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,109, 97,120, 40,100, +111,116, 40,110, 44, 32,104, 41, 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97, +120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,108, 32, 61, + 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,108, 41, 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32, 97, +110,103,108,101, 32, 61, 32,116, 97,110, 40, 97, 99,111,115, 40,110,104, 41, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,108,112, +104, 97, 32, 61, 32,109, 97,120, 40,114,109,115, 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 61, + 32,110,108, 32, 42, 32, 40, 49, 46, 48, 47, 40, 52, 46, 48, 42, 77, 95, 80, 73, 42, 97,108,112,104, 97, 42, 97,108,112,104, 97, + 41, 41, 42, 40,101,120,112, 95, 98,108,101,110,100,101,114, 40, 45, 40, 97,110,103,108,101, 42, 97,110,103,108,101, 41, 47, 40, + 97,108,112,104, 97, 42, 97,108,112,104, 97, 41, 41, 47, 40,115,113,114,116, 40,110,118, 42,110,108, 41, 41, 41, 59, 10,125, 10, + 10,118,111,105,100, 32,115,104, 97,100,101, 95,116,111,111,110, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, + 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,115,105,122,101, 44, 32,102,108,111, 97,116, 32, +116,115,109,111,111,116,104, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118, +101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, 97,116, + 32,114,115,108,116, 32, 61, 32,100,111,116, 40,104, 44, 32,110, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103, 32, 61, 32, + 97, 99,111,115, 40,114,115,108,116, 41, 59, 10, 10, 9,105,102, 40, 97,110,103, 32, 60, 32,115,105,122,101, 41, 32,114,115,108, +116, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40, 97,110,103, 32, 62, 61, 32, 40,115,105,122,101, 32, 43, + 32,116,115,109,111,111,116,104, 41, 32,124,124, 32,116,115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, 48, 41, 32,114,115,108, +116, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,114,115,108,116, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, 97,110, +103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111,111,116,104, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, +114,115,108,116, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,115,112,101, 99, 95, 97,114,101, 97, 95,105,110, +112, 40,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 44, 32,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117,116, 32, +102,108,111, 97,116, 32,111,117,116,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99,102, 97, 99, 32, + 61, 32,115,112,101, 99,102, 97, 99, 42,105,110,112, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,115,112,101, + 99, 95,116, 40,102,108,111, 97,116, 32,115,104, 97,100,102, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 44, 32,102, +108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,116, 32, 61, 32,115,104, 97,100,102, 97, 99, 42,115,112,101, 99, 42,118,105, +115,105,102, 97, 99, 42,115,112,101, 99,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, + 95,115,112,101, 99, 40,102,108,111, 97,116, 32,116, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111,108, 44, 32,118,101, 99, + 51, 32,115,112,101, 99, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111, +117,116, 99,111,108, 32, 61, 32,116, 42,108, 97,109,112, 99,111,108, 42,115,112,101, 99, 99,111,108, 59, 10,125, 10, 10,118,111, +105,100, 32,115,104, 97,100,101, 95, 97,100,100, 40,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, + 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, + 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100,100, 40, +118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32, +111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, + 32, 43, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 95, + 99,108, 97,109,112,101,100, 40,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117, +116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 32, + 43, 32,109, 97,120, 40, 99,111,108, 50, 44, 32,118,101, 99, 52, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, + 48, 46, 48, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100,100, 95, 99,108, 97,109,112,101, 100, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99, -111,108, 32, 43, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100, -100, 95, 99,108, 97,109,112,101,100, 40,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32, -111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, - 49, 32, 43, 32,109, 97,120, 40, 99,111,108, 50, 44, 32,118,101, 99, 52, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, - 44, 32, 48, 46, 48, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100,100, 95, 99,108, 97,109, -112,101,100, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111, -108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, - 32, 99,111,108, 32, 43, 32,109, 97,120, 40, 99,111,108, 49, 42, 99,111,108, 50, 44, 32,118,101, 99, 52, 40, 48, 46, 48, 44, 32, - 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, - 97,100,100,102, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 44, 32,118,101, 99, 52, 32, 99,111,108, - 49, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, - 99,111,108, 32, 43, 32,102, 42, 99,111,108, 49, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 40, -118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111, -117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10,125, 10, - 10,118,111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 95,118, 97,108,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, - 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111, -117,116, 99,111,108, 32, 61, 32, 99,111,108, 42,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111, - 98, 99,111,108,111,114, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, 32,111, 98, 99,111,108, 44, 32,111,117,116, - 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99, -111,108, 46,114,103, 98, 42,111, 98, 99,111,108, 46,114,103, 98, 44, 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105, -100, 32,114, 97,109,112, 95,114,103, 98,116,111, 98,119, 40,118,101, 99, 51, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102, -108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, - 42, 48, 46, 51, 32, 43, 32, 99,111,108,111,114, 46,103, 42, 48, 46, 53, 56, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, - 49, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111,110,108,121, 95,115,104, 97,100,111,119, 40,102,108, -111, 97,116, 32,105, 44, 32,102,108,111, 97,116, 32,115,104, 97,100,102, 97, 99, 44, 32,102,108,111, 97,116, 32,101,110,101,114, -103,121, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,104, 97,100,102, 97, 99, 41, 10,123, 10, 9,111,117,116, -115,104, 97,100,102, 97, 99, 32, 61, 32,105, 42,101,110,101,114,103,121, 42, 40, 49, 46, 48, 32, 45, 32,115,104, 97,100,102, 97, - 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111,110,108,121, 95,115,104, 97,100,111,119, 95,100,105, -102,102,117,115,101, 40,102,108,111, 97,116, 32,115,104, 97,100,102, 97, 99, 44, 32,118,101, 99, 51, 32,114,103, 98, 44, 32,118, -101, 99, 52, 32,100,105,102,102, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,100,105,102,102, 41, 10,123, 10, 9,111, -117,116,100,105,102,102, 32, 61, 32,100,105,102,102, 32, 45, 32,118,101, 99, 52, 40,114,103, 98, 42,115,104, 97,100,102, 97, 99, - 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111,110,108,121, 95,115,104, 97,100,111, -119, 95,115,112,101, 99,117,108, 97,114, 40,102,108,111, 97,116, 32,115,104, 97,100,102, 97, 99, 44, 32,118,101, 99, 51, 32,115, -112,101, 99,114,103, 98, 44, 32,118,101, 99, 52, 32,115,112,101, 99, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,115, -112,101, 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99, 32, 61, 32,115,112,101, 99, 32, 45, 32,118,101, 99, 52, 40,115,112, -101, 99,114,103, 98, 42,115,104, 97,100,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,115, -116, 95,115,104, 97,100,111,119, 98,117,102, 40,118,101, 99, 51, 32,114, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 83, -104, 97,100,111,119, 32,115,104, 97,100,111,119,109, 97,112, 44, 32,109, 97,116, 52, 32,115,104, 97,100,111,119,112,101,114,115, -109, 97,116, 44, 32,102,108,111, 97,116, 32,115,104, 97,100,111,119, 98,105, 97,115, 44, 32,102,108,111, 97,116, 32,105,110,112, - 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,105,102, 40,105,110,112, 32, 60, 61, - 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,101,115,117,108,116, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, - 32,123, 10, 9, 9,118,101, 99, 52, 32, 99,111, 32, 61, 32,115,104, 97,100,111,119,112,101,114,115,109, 97,116, 42,118,101, 99, - 52, 40,114, 99,111, 44, 32, 49, 46, 48, 41, 59, 10, 10, 9, 9, 47, 47,102,108,111, 97,116, 32, 98,105, 97,115, 32, 61, 32, 40, - 49, 46, 53, 32, 45, 32,105,110,112, 42,105,110,112, 41, 42,115,104, 97,100,111,119, 98,105, 97,115, 59, 10, 9, 9, 99,111, 46, -122, 32, 45, 61, 32,115,104, 97,100,111,119, 98,105, 97,115, 42, 99,111, 46,119, 59, 10, 10, 9, 9,114,101,115,117,108,116, 32, - 61, 32,115,104, 97,100,111,119, 50, 68, 80,114,111,106, 40,115,104, 97,100,111,119,109, 97,112, 44, 32, 99,111, 41, 46,120, 59, - 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,101,120,112,111,115,117,114,101, 95, 99,111,114,114,101, - 99,116, 40,118,101, 99, 51, 32, 99,111,108, 44, 32,102,108,111, 97,116, 32,108,105,110,102, 97, 99, 44, 32,102,108,111, 97,116, - 32,108,111,103,102, 97, 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, - 99,111,108, 32, 61, 32,108,105,110,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32,101,120,112, 40, 99,111,108, 42,108,111,103,102, - 97, 99, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109,105,115,116, 95,102, 97, 99,116,111,114, 40, -118,101, 99, 51, 32, 99,111, 44, 32,102,108,111, 97,116, 32,109,105,115,116,115,116, 97, 44, 32,102,108,111, 97,116, 32,109,105, -115,116,100,105,115,116, 44, 32,102,108,111, 97,116, 32,109,105,115,116,116,121,112,101, 44, 32,102,108,111, 97,116, 32,109,105, -115,105, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, - 97, 99, 44, 32,122, 99,111,114, 59, 10, 10, 9,122, 99,111,114, 32, 61, 32, 40,103,108, 95, 80,114,111,106,101, 99,116,105,111, -110, 77, 97,116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, 48, 46, 48, 41, 63, 32,108,101,110,103,116,104, 40, 99,111, - 41, 58, 32, 45, 99,111, 91, 50, 93, 59, 10, 9, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40, 40,122, 99,111,114, 45, -109,105,115,116,115,116, 97, 41, 47,109,105,115,116,100,105,115,116, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,105, -102, 40,109,105,115,116,116,121,112,101, 32, 61, 61, 32, 48, 46, 48, 41, 32,102, 97, 99, 32, 42, 61, 32,102, 97, 99, 59, 10, 9, -101,108,115,101, 32,105,102, 40,109,105,115,116,116,121,112,101, 32, 61, 61, 32, 49, 46, 48, 41, 59, 10, 9,101,108,115,101, 32, -102, 97, 99, 32, 61, 32,115,113,114,116, 40,102, 97, 99, 41, 59, 10, 10, 9,111,117,116,102, 97, 99, 32, 61, 32, 49, 46, 48, 32, - 45, 32, 40, 49, 46, 48, 45,102, 97, 99, 41, 42, 40, 49, 46, 48, 45,109,105,115,105, 41, 59, 10,125, 10, 10,118,111,105,100, 32, -115,104, 97,100,101, 95,119,111,114,108,100, 95,109,105,120, 40,118,101, 99, 51, 32,104,111,114, 44, 32,118,101, 99, 52, 32, 99, -111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, - 99, 32, 61, 32, 99,108, 97,109,112, 40, 99,111,108, 46, 97, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, - 99,111,108, 32, 61, 32,118,101, 99, 52, 40,109,105,120, 40,104,111,114, 44, 32, 99,111,108, 46,114,103, 98, 44, 32,102, 97, 99, - 41, 44, 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,108,112,104, 97, 95,111, -112, 97,113,117,101, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, - 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 49, 46, 48, 41, 59, - 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,108,112,104, 97, 95,111, 98, 99,111,108,111,114, 40,118,101, 99, - 52, 32, 99,111,108, 44, 32,118,101, 99, 52, 32,111, 98, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, -111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 99,111, -108, 46, 97, 42,111, 98, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 78, 69, - 87, 32, 83, 72, 65, 68, 69, 82, 32, 85, 84, 73, 76, 73, 84, 73, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 47, 10, 10,102,108,111, 97,116, 32,102,114,101,115,110,101,108, 95,100,105,101,108,101, 99,116,114,105, 99, 40,118,101, 99, - 51, 32, 73,110, 99,111,109,105,110,103, 44, 32,118,101, 99, 51, 32, 78,111,114,109, 97,108, 44, 32,102,108,111, 97,116, 32,101, -116, 97, 41, 10,123, 10, 32, 32, 32, 32, 47, 42, 32, 99,111,109,112,117,116,101, 32,102,114,101,115,110,101,108, 32,114,101,102, -108,101, 99,116, 97,110, 99,101, 32,119,105,116,104,111,117,116, 32,101,120,112,108,105, 99,105,116,108,121, 32, 99,111,109,112, -117,116,105,110,103, 10, 32, 32, 32, 32, 32, 32, 32,116,104,101, 32,114,101,102,114, 97, 99,116,101,100, 32,100,105,114,101, 99, -116,105,111,110, 32, 42, 47, 10, 32, 32, 32, 32,102,108,111, 97,116, 32, 99, 32, 61, 32, 97, 98,115, 40,100,111,116, 40, 73,110, - 99,111,109,105,110,103, 44, 32, 78,111,114,109, 97,108, 41, 41, 59, 10, 32, 32, 32, 32,102,108,111, 97,116, 32,103, 32, 61, 32, -101,116, 97, 32, 42, 32,101,116, 97, 32, 45, 32, 49, 46, 48, 32, 43, 32, 99, 32, 42, 32, 99, 59, 10, 32, 32, 32, 32,102,108,111, - 97,116, 32,114,101,115,117,108,116, 59, 10, 10, 32, 32, 32, 32,105,102, 40,103, 32, 62, 32, 48, 46, 48, 41, 32,123, 10, 32, 32, - 32, 32, 32, 32, 32, 32,103, 32, 61, 32,115,113,114,116, 40,103, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32,102,108,111, 97,116, - 32, 65, 32, 61, 40,103, 32, 45, 32, 99, 41, 47, 40,103, 32, 43, 32, 99, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32,102,108,111, - 97,116, 32, 66, 32, 61, 40, 99, 32, 42, 40,103, 32, 43, 32, 99, 41, 45, 32, 49, 46, 48, 41, 47, 40, 99, 32, 42, 40,103, 32, 45, - 32, 99, 41, 43, 32, 49, 46, 48, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32,114,101,115,117,108,116, 32, 61, 32, 48, 46, 53, 32, - 42, 32, 65, 32, 42, 32, 65, 32, 42, 40, 49, 46, 48, 32, 43, 32, 66, 32, 42, 32, 66, 41, 59, 10, 32, 32, 32, 32,125, 10, 32, 32, - 32, 32,101,108,115,101, 10, 32, 32, 32, 32, 32, 32, 32, 32,114,101,115,117,108,116, 32, 61, 32, 49, 46, 48, 59, 32, 32, 47, 42, - 32, 84, 73, 82, 32, 40,110,111, 32,114,101,102,114, 97, 99,116,101,100, 32, 99,111,109,112,111,110,101,110,116, 41, 32, 42, 47, - 10, 10, 32, 32, 32, 32,114,101,116,117,114,110, 32,114,101,115,117,108,116, 59, 10,125, 10, 10,102,108,111, 97,116, 32,104,121, -112,111,116, 40,102,108,111, 97,116, 32,120, 44, 32,102,108,111, 97,116, 32,121, 41, 10,123, 10, 9,114,101,116,117,114,110, 32, -115,113,114,116, 40,120, 42,120, 32, 43, 32,121, 42,121, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 32, 78, 69, 87, 32, 83, 72, 65, 68, 69, 82, 32, 78, 79, 68, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 47, 10, 10, 35,100,101,102,105,110,101, 32, 78, 85, 77, 95, 76, 73, 71, 72, 84, 83, 32, 51, 10, 10, 47, 42, 32, 98,115,100, -102,115, 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,100,105,102,102,117,115,101, 40,118,101, - 99, 52, 32, 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104,110,101,115,115, 44, 32,118,101, 99, 51, 32, - 78, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9, 47, 42, 32, 97,109, 98,105,101,110, -116, 32,108,105,103,104,116, 32, 42, 47, 10, 9,118,101, 99, 51, 32, 76, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 50, 41, 59, 10, - 10, 9, 47, 42, 32,100,105,114,101, 99,116,105,111,110, 97,108, 32,108,105,103,104,116,115, 32, 42, 47, 10, 9,102,111,114, 40, -105,110,116, 32,105, 32, 61, 32, 48, 59, 32,105, 32, 60, 32, 78, 85, 77, 95, 76, 73, 71, 72, 84, 83, 59, 32,105, 43, 43, 41, 32, -123, 10, 9, 9,118,101, 99, 51, 32,108,105,103,104,116, 95,112,111,115,105,116,105,111,110, 32, 61, 32,103,108, 95, 76,105,103, -104,116, 83,111,117,114, 99,101, 91,105, 93, 46,112,111,115,105,116,105,111,110, 46,120,121,122, 59, 10, 9, 9,118,101, 99, 51, - 32,108,105,103,104,116, 95,100,105,102,102,117,115,101, 32, 61, 32,103,108, 95, 76,105,103,104,116, 83,111,117,114, 99,101, 91, -105, 93, 46,100,105,102,102,117,115,101, 46,114,103, 98, 59, 10, 10, 9, 9,102,108,111, 97,116, 32, 98,115,100,102, 32, 61, 32, -109, 97,120, 40,100,111,116, 40, 78, 44, 32,108,105,103,104,116, 95,112,111,115,105,116,105,111,110, 41, 44, 32, 48, 46, 48, 41, - 59, 10, 9, 9, 76, 32, 43, 61, 32,108,105,103,104,116, 95,100,105,102,102,117,115,101, 42, 98,115,100,102, 59, 10, 9,125, 10, - 10, 9,114,101,115,117,108,116, 32, 61, 32,118,101, 99, 52, 40, 76, 42, 99,111,108,111,114, 46,114,103, 98, 44, 32, 49, 46, 48, - 41, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,103,108,111,115,115,121, 40,118,101, 99, 52, +111,108, 32, 43, 32,109, 97,120, 40, 99,111,108, 49, 42, 99,111,108, 50, 44, 32,118,101, 99, 52, 40, 48, 46, 48, 44, 32, 48, 46, + 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100, +100,102, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, + 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111, +108, 32, 43, 32,102, 42, 99,111,108, 49, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 40,118,101, + 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, + 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10,125, 10, 10,118, +111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 95,118, 97,108,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118, +101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, + 99,111,108, 32, 61, 32, 99,111,108, 42,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111, 98, 99, +111,108,111,114, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, 32,111, 98, 99,111,108, 44, 32,111,117,116, 32,118, +101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, + 46,114,103, 98, 42,111, 98, 99,111,108, 46,114,103, 98, 44, 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32, +114, 97,109,112, 95,114,103, 98,116,111, 98,119, 40,118,101, 99, 51, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102,108,111, + 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, 42, 48, + 46, 51, 32, 43, 32, 99,111,108,111,114, 46,103, 42, 48, 46, 53, 56, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, 49, 50, + 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111,110,108,121, 95,115,104, 97,100,111,119, 40,102,108,111, 97, +116, 32,105, 44, 32,102,108,111, 97,116, 32,115,104, 97,100,102, 97, 99, 44, 32,102,108,111, 97,116, 32,101,110,101,114,103,121, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,104, 97,100,102, 97, 99, 41, 10,123, 10, 9,111,117,116,115,104, + 97,100,102, 97, 99, 32, 61, 32,105, 42,101,110,101,114,103,121, 42, 40, 49, 46, 48, 32, 45, 32,115,104, 97,100,102, 97, 99, 41, + 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111,110,108,121, 95,115,104, 97,100,111,119, 95,100,105,102,102, +117,115,101, 40,102,108,111, 97,116, 32,115,104, 97,100,102, 97, 99, 44, 32,118,101, 99, 51, 32,114,103, 98, 44, 32,118,101, 99, + 52, 32,100,105,102,102, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,100,105,102,102, 41, 10,123, 10, 9,111,117,116, +100,105,102,102, 32, 61, 32,100,105,102,102, 32, 45, 32,118,101, 99, 52, 40,114,103, 98, 42,115,104, 97,100,102, 97, 99, 44, 32, + 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111,110,108,121, 95,115,104, 97,100,111,119, 95, +115,112,101, 99,117,108, 97,114, 40,102,108,111, 97,116, 32,115,104, 97,100,102, 97, 99, 44, 32,118,101, 99, 51, 32,115,112,101, + 99,114,103, 98, 44, 32,118,101, 99, 52, 32,115,112,101, 99, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,115,112,101, + 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99, 32, 61, 32,115,112,101, 99, 32, 45, 32,118,101, 99, 52, 40,115,112,101, 99, +114,103, 98, 42,115,104, 97,100,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,115,116, 95, +115,104, 97,100,111,119, 98,117,102, 40,118,101, 99, 51, 32,114, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 83,104, 97, +100,111,119, 32,115,104, 97,100,111,119,109, 97,112, 44, 32,109, 97,116, 52, 32,115,104, 97,100,111,119,112,101,114,115,109, 97, +116, 44, 32,102,108,111, 97,116, 32,115,104, 97,100,111,119, 98,105, 97,115, 44, 32,102,108,111, 97,116, 32,105,110,112, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,105,102, 40,105,110,112, 32, 60, 61, 32, 48, + 46, 48, 41, 32,123, 10, 9, 9,114,101,115,117,108,116, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, + 10, 9, 9,118,101, 99, 52, 32, 99,111, 32, 61, 32,115,104, 97,100,111,119,112,101,114,115,109, 97,116, 42,118,101, 99, 52, 40, +114, 99,111, 44, 32, 49, 46, 48, 41, 59, 10, 10, 9, 9, 47, 47,102,108,111, 97,116, 32, 98,105, 97,115, 32, 61, 32, 40, 49, 46, + 53, 32, 45, 32,105,110,112, 42,105,110,112, 41, 42,115,104, 97,100,111,119, 98,105, 97,115, 59, 10, 9, 9, 99,111, 46,122, 32, + 45, 61, 32,115,104, 97,100,111,119, 98,105, 97,115, 42, 99,111, 46,119, 59, 10, 10, 9, 9,114,101,115,117,108,116, 32, 61, 32, +115,104, 97,100,111,119, 50, 68, 80,114,111,106, 40,115,104, 97,100,111,119,109, 97,112, 44, 32, 99,111, 41, 46,120, 59, 10, 9, +125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,101,120,112,111,115,117,114,101, 95, 99,111,114,114,101, 99,116, + 40,118,101, 99, 51, 32, 99,111,108, 44, 32,102,108,111, 97,116, 32,108,105,110,102, 97, 99, 44, 32,102,108,111, 97,116, 32,108, +111,103,102, 97, 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111, +108, 32, 61, 32,108,105,110,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32,101,120,112, 40, 99,111,108, 42,108,111,103,102, 97, 99, + 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109,105,115,116, 95,102, 97, 99,116,111,114, 40,118,101, + 99, 51, 32, 99,111, 44, 32,102,108,111, 97,116, 32,109,105,115,116,115,116, 97, 44, 32,102,108,111, 97,116, 32,109,105,115,116, +100,105,115,116, 44, 32,102,108,111, 97,116, 32,109,105,115,116,116,121,112,101, 44, 32,102,108,111, 97,116, 32,109,105,115,105, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, + 44, 32,122, 99,111,114, 59, 10, 10, 9,122, 99,111,114, 32, 61, 32, 40,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, + 97,116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, 48, 46, 48, 41, 63, 32,108,101,110,103,116,104, 40, 99,111, 41, 58, + 32, 45, 99,111, 91, 50, 93, 59, 10, 9, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40, 40,122, 99,111,114, 45,109,105, +115,116,115,116, 97, 41, 47,109,105,115,116,100,105,115,116, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,105,102, 40, +109,105,115,116,116,121,112,101, 32, 61, 61, 32, 48, 46, 48, 41, 32,102, 97, 99, 32, 42, 61, 32,102, 97, 99, 59, 10, 9,101,108, +115,101, 32,105,102, 40,109,105,115,116,116,121,112,101, 32, 61, 61, 32, 49, 46, 48, 41, 59, 10, 9,101,108,115,101, 32,102, 97, + 99, 32, 61, 32,115,113,114,116, 40,102, 97, 99, 41, 59, 10, 10, 9,111,117,116,102, 97, 99, 32, 61, 32, 49, 46, 48, 32, 45, 32, + 40, 49, 46, 48, 45,102, 97, 99, 41, 42, 40, 49, 46, 48, 45,109,105,115,105, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, + 97,100,101, 95,119,111,114,108,100, 95,109,105,120, 40,118,101, 99, 51, 32,104,111,114, 44, 32,118,101, 99, 52, 32, 99,111,108, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, 32, + 61, 32, 99,108, 97,109,112, 40, 99,111,108, 46, 97, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111, +108, 32, 61, 32,118,101, 99, 52, 40,109,105,120, 40,104,111,114, 44, 32, 99,111,108, 46,114,103, 98, 44, 32,102, 97, 99, 41, 44, + 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,108,112,104, 97, 95,111,112, 97, +113,117,101, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, + 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 49, 46, 48, 41, 59, 10,125, + 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,108,112,104, 97, 95,111, 98, 99,111,108,111,114, 40,118,101, 99, 52, 32, + 99,111,108, 44, 32,118,101, 99, 52, 32,111, 98, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, + 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 99,111,108, 46, + 97, 42,111, 98, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 78, 69, 87, 32, + 83, 72, 65, 68, 69, 82, 32, 85, 84, 73, 76, 73, 84, 73, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, + 10, 10,102,108,111, 97,116, 32,102,114,101,115,110,101,108, 95,100,105,101,108,101, 99,116,114,105, 99, 40,118,101, 99, 51, 32, + 73,110, 99,111,109,105,110,103, 44, 32,118,101, 99, 51, 32, 78,111,114,109, 97,108, 44, 32,102,108,111, 97,116, 32,101,116, 97, + 41, 10,123, 10, 32, 32, 32, 32, 47, 42, 32, 99,111,109,112,117,116,101, 32,102,114,101,115,110,101,108, 32,114,101,102,108,101, + 99,116, 97,110, 99,101, 32,119,105,116,104,111,117,116, 32,101,120,112,108,105, 99,105,116,108,121, 32, 99,111,109,112,117,116, +105,110,103, 10, 32, 32, 32, 32, 32, 32, 32,116,104,101, 32,114,101,102,114, 97, 99,116,101,100, 32,100,105,114,101, 99,116,105, +111,110, 32, 42, 47, 10, 32, 32, 32, 32,102,108,111, 97,116, 32, 99, 32, 61, 32, 97, 98,115, 40,100,111,116, 40, 73,110, 99,111, +109,105,110,103, 44, 32, 78,111,114,109, 97,108, 41, 41, 59, 10, 32, 32, 32, 32,102,108,111, 97,116, 32,103, 32, 61, 32,101,116, + 97, 32, 42, 32,101,116, 97, 32, 45, 32, 49, 46, 48, 32, 43, 32, 99, 32, 42, 32, 99, 59, 10, 32, 32, 32, 32,102,108,111, 97,116, + 32,114,101,115,117,108,116, 59, 10, 10, 32, 32, 32, 32,105,102, 40,103, 32, 62, 32, 48, 46, 48, 41, 32,123, 10, 32, 32, 32, 32, + 32, 32, 32, 32,103, 32, 61, 32,115,113,114,116, 40,103, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32,102,108,111, 97,116, 32, 65, + 32, 61, 40,103, 32, 45, 32, 99, 41, 47, 40,103, 32, 43, 32, 99, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32,102,108,111, 97,116, + 32, 66, 32, 61, 40, 99, 32, 42, 40,103, 32, 43, 32, 99, 41, 45, 32, 49, 46, 48, 41, 47, 40, 99, 32, 42, 40,103, 32, 45, 32, 99, + 41, 43, 32, 49, 46, 48, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32,114,101,115,117,108,116, 32, 61, 32, 48, 46, 53, 32, 42, 32, + 65, 32, 42, 32, 65, 32, 42, 40, 49, 46, 48, 32, 43, 32, 66, 32, 42, 32, 66, 41, 59, 10, 32, 32, 32, 32,125, 10, 32, 32, 32, 32, +101,108,115,101, 10, 32, 32, 32, 32, 32, 32, 32, 32,114,101,115,117,108,116, 32, 61, 32, 49, 46, 48, 59, 32, 32, 47, 42, 32, 84, + 73, 82, 32, 40,110,111, 32,114,101,102,114, 97, 99,116,101,100, 32, 99,111,109,112,111,110,101,110,116, 41, 32, 42, 47, 10, 10, + 32, 32, 32, 32,114,101,116,117,114,110, 32,114,101,115,117,108,116, 59, 10,125, 10, 10,102,108,111, 97,116, 32,104,121,112,111, +116, 40,102,108,111, 97,116, 32,120, 44, 32,102,108,111, 97,116, 32,121, 41, 10,123, 10, 9,114,101,116,117,114,110, 32,115,113, +114,116, 40,120, 42,120, 32, 43, 32,121, 42,121, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 78, + 69, 87, 32, 83, 72, 65, 68, 69, 82, 32, 78, 79, 68, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, + 10, 10, 35,100,101,102,105,110,101, 32, 78, 85, 77, 95, 76, 73, 71, 72, 84, 83, 32, 51, 10, 10, 47, 42, 32, 98,115,100,102,115, + 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,100,105,102,102,117,115,101, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104,110,101,115,115, 44, 32,118,101, 99, 51, 32, 78, 44, - 32,118,101, 99, 51, 32, 73, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9, 47, 42, 32, - 97,109, 98,105,101,110,116, 32,108,105,103,104,116, 32, 42, 47, 10, 9,118,101, 99, 51, 32, 76, 32, 61, 32,118,101, 99, 51, 40, - 48, 46, 50, 41, 59, 10, 10, 9, 47, 42, 32,100,105,114,101, 99,116,105,111,110, 97,108, 32,108,105,103,104,116,115, 32, 42, 47, - 10, 9,102,111,114, 40,105,110,116, 32,105, 32, 61, 32, 48, 59, 32,105, 32, 60, 32, 78, 85, 77, 95, 76, 73, 71, 72, 84, 83, 59, - 32,105, 43, 43, 41, 32,123, 10, 9, 9,118,101, 99, 51, 32,108,105,103,104,116, 95,112,111,115,105,116,105,111,110, 32, 61, 32, -103,108, 95, 76,105,103,104,116, 83,111,117,114, 99,101, 91,105, 93, 46,112,111,115,105,116,105,111,110, 46,120,121,122, 59, 10, - 9, 9,118,101, 99, 51, 32, 72, 32, 61, 32,103,108, 95, 76,105,103,104,116, 83,111,117,114, 99,101, 91,105, 93, 46,104, 97,108, -102, 86,101, 99,116,111,114, 46,120,121,122, 59, 10, 9, 9,118,101, 99, 51, 32,108,105,103,104,116, 95,100,105,102,102,117,115, -101, 32, 61, 32,103,108, 95, 76,105,103,104,116, 83,111,117,114, 99,101, 91,105, 93, 46,100,105,102,102,117,115,101, 46,114,103, - 98, 59, 10, 9, 9,118,101, 99, 51, 32,108,105,103,104,116, 95,115,112,101, 99,117,108, 97,114, 32, 61, 32,103,108, 95, 76,105, -103,104,116, 83,111,117,114, 99,101, 91,105, 93, 46,115,112,101, 99,117,108, 97,114, 46,114,103, 98, 59, 10, 10, 9, 9, 47, 42, - 32,119,101, 32,109,105,120, 32,105,110, 32,115,111,109,101, 32,100,105,102,102,117,115,101, 32,115,111, 32,108,111,119, 32,114, -111,117,103,104,110,101,115,115, 32,115,116,105,108,108, 32,115,104,111,119,115, 32,117,112, 32, 42, 47, 10, 9, 9,102,108,111, - 97,116, 32, 98,115,100,102, 32, 61, 32, 48, 46, 53, 42,112,111,119, 40,109, 97,120, 40,100,111,116, 40, 78, 44, 32, 72, 41, 44, - 32, 48, 46, 48, 41, 44, 32, 49, 46, 48, 47,114,111,117,103,104,110,101,115,115, 41, 59, 10, 9, 9, 98,115,100,102, 32, 43, 61, - 32, 48, 46, 53, 42,109, 97,120, 40,100,111,116, 40, 78, 44, 32,108,105,103,104,116, 95,112,111,115,105,116,105,111,110, 41, 44, - 32, 48, 46, 48, 41, 59, 10, 9, 9, 76, 32, 43, 61, 32,108,105,103,104,116, 95,115,112,101, 99,117,108, 97,114, 42, 98,115,100, -102, 59, 10, 9,125, 10, 10, 9,114,101,115,117,108,116, 32, 61, 32,118,101, 99, 52, 40, 76, 42, 99,111,108,111,114, 46,114,103, - 98, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95, 97,110,105,115,111, -116,114,111,112,105, 99, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104,110,101, -115,115, 85, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104,110,101,115,115, 86, 44, 32,118,101, 99, 51, 32, 78, 44, 32,118, -101, 99, 51, 32, 73, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,110,111,100,101, 95, - 98,115,100,102, 95,100,105,102,102,117,115,101, 40, 99,111,108,111,114, 44, 32, 48, 46, 48, 44, 32, 78, 44, 32,114,101,115,117, -108,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,103,108, 97,115,115, 40,118,101, 99, - 52, 32, 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104,110,101,115,115, 44, 32,102,108,111, 97,116, 32, -105,111,114, 44, 32,118,101, 99, 51, 32, 78, 44, 32,118,101, 99, 51, 32, 73, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101, -115,117,108,116, 41, 10,123, 10, 9,110,111,100,101, 95, 98,115,100,102, 95,100,105,102,102,117,115,101, 40, 99,111,108,111,114, - 44, 32, 48, 46, 48, 44, 32, 78, 44, 32,114,101,115,117,108,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, - 98,115,100,102, 95,116,114, 97,110,115,108,117, 99,101,110,116, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,118,101, 99, - 51, 32, 78, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,110,111,100,101, 95, 98,115, + 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9, 47, 42, 32, 97,109, 98,105,101,110,116, 32, +108,105,103,104,116, 32, 42, 47, 10, 9,118,101, 99, 51, 32, 76, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 50, 41, 59, 10, 10, 9, + 47, 42, 32,100,105,114,101, 99,116,105,111,110, 97,108, 32,108,105,103,104,116,115, 32, 42, 47, 10, 9,102,111,114, 40,105,110, +116, 32,105, 32, 61, 32, 48, 59, 32,105, 32, 60, 32, 78, 85, 77, 95, 76, 73, 71, 72, 84, 83, 59, 32,105, 43, 43, 41, 32,123, 10, + 9, 9,118,101, 99, 51, 32,108,105,103,104,116, 95,112,111,115,105,116,105,111,110, 32, 61, 32,103,108, 95, 76,105,103,104,116, + 83,111,117,114, 99,101, 91,105, 93, 46,112,111,115,105,116,105,111,110, 46,120,121,122, 59, 10, 9, 9,118,101, 99, 51, 32,108, +105,103,104,116, 95,100,105,102,102,117,115,101, 32, 61, 32,103,108, 95, 76,105,103,104,116, 83,111,117,114, 99,101, 91,105, 93, + 46,100,105,102,102,117,115,101, 46,114,103, 98, 59, 10, 10, 9, 9,102,108,111, 97,116, 32, 98,115,100,102, 32, 61, 32,109, 97, +120, 40,100,111,116, 40, 78, 44, 32,108,105,103,104,116, 95,112,111,115,105,116,105,111,110, 41, 44, 32, 48, 46, 48, 41, 59, 10, + 9, 9, 76, 32, 43, 61, 32,108,105,103,104,116, 95,100,105,102,102,117,115,101, 42, 98,115,100,102, 59, 10, 9,125, 10, 10, 9, +114,101,115,117,108,116, 32, 61, 32,118,101, 99, 52, 40, 76, 42, 99,111,108,111,114, 46,114,103, 98, 44, 32, 49, 46, 48, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,103,108,111,115,115,121, 40,118,101, 99, 52, 32, 99, +111,108,111,114, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104,110,101,115,115, 44, 32,118,101, 99, 51, 32, 78, 44, 32,118, +101, 99, 51, 32, 73, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9, 47, 42, 32, 97,109, + 98,105,101,110,116, 32,108,105,103,104,116, 32, 42, 47, 10, 9,118,101, 99, 51, 32, 76, 32, 61, 32,118,101, 99, 51, 40, 48, 46, + 50, 41, 59, 10, 10, 9, 47, 42, 32,100,105,114,101, 99,116,105,111,110, 97,108, 32,108,105,103,104,116,115, 32, 42, 47, 10, 9, +102,111,114, 40,105,110,116, 32,105, 32, 61, 32, 48, 59, 32,105, 32, 60, 32, 78, 85, 77, 95, 76, 73, 71, 72, 84, 83, 59, 32,105, + 43, 43, 41, 32,123, 10, 9, 9,118,101, 99, 51, 32,108,105,103,104,116, 95,112,111,115,105,116,105,111,110, 32, 61, 32,103,108, + 95, 76,105,103,104,116, 83,111,117,114, 99,101, 91,105, 93, 46,112,111,115,105,116,105,111,110, 46,120,121,122, 59, 10, 9, 9, +118,101, 99, 51, 32, 72, 32, 61, 32,103,108, 95, 76,105,103,104,116, 83,111,117,114, 99,101, 91,105, 93, 46,104, 97,108,102, 86, +101, 99,116,111,114, 46,120,121,122, 59, 10, 9, 9,118,101, 99, 51, 32,108,105,103,104,116, 95,100,105,102,102,117,115,101, 32, + 61, 32,103,108, 95, 76,105,103,104,116, 83,111,117,114, 99,101, 91,105, 93, 46,100,105,102,102,117,115,101, 46,114,103, 98, 59, + 10, 9, 9,118,101, 99, 51, 32,108,105,103,104,116, 95,115,112,101, 99,117,108, 97,114, 32, 61, 32,103,108, 95, 76,105,103,104, +116, 83,111,117,114, 99,101, 91,105, 93, 46,115,112,101, 99,117,108, 97,114, 46,114,103, 98, 59, 10, 10, 9, 9, 47, 42, 32,119, +101, 32,109,105,120, 32,105,110, 32,115,111,109,101, 32,100,105,102,102,117,115,101, 32,115,111, 32,108,111,119, 32,114,111,117, +103,104,110,101,115,115, 32,115,116,105,108,108, 32,115,104,111,119,115, 32,117,112, 32, 42, 47, 10, 9, 9,102,108,111, 97,116, + 32, 98,115,100,102, 32, 61, 32, 48, 46, 53, 42,112,111,119, 40,109, 97,120, 40,100,111,116, 40, 78, 44, 32, 72, 41, 44, 32, 48, + 46, 48, 41, 44, 32, 49, 46, 48, 47,114,111,117,103,104,110,101,115,115, 41, 59, 10, 9, 9, 98,115,100,102, 32, 43, 61, 32, 48, + 46, 53, 42,109, 97,120, 40,100,111,116, 40, 78, 44, 32,108,105,103,104,116, 95,112,111,115,105,116,105,111,110, 41, 44, 32, 48, + 46, 48, 41, 59, 10, 9, 9, 76, 32, 43, 61, 32,108,105,103,104,116, 95,115,112,101, 99,117,108, 97,114, 42, 98,115,100,102, 59, + 10, 9,125, 10, 10, 9,114,101,115,117,108,116, 32, 61, 32,118,101, 99, 52, 40, 76, 42, 99,111,108,111,114, 46,114,103, 98, 44, + 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95, 97,110,105,115,111,116,114, +111,112,105, 99, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104,110,101,115,115, + 85, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104,110,101,115,115, 86, 44, 32,118,101, 99, 51, 32, 78, 44, 32,118,101, 99, + 51, 32, 73, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,110,111,100,101, 95, 98,115, 100,102, 95,100,105,102,102,117,115,101, 40, 99,111,108,111,114, 44, 32, 48, 46, 48, 44, 32, 78, 44, 32,114,101,115,117,108,116, - 41, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,116,114, 97,110,115,112, 97,114,101,110,116, - 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, - 9, 47, 42, 32,116,104,105,115, 32,105,115,110, 39,116, 32,114,105,103,104,116, 32, 42, 47, 10, 9,114,101,115,117,108,116, 46, -114, 32, 61, 32, 99,111,108,111,114, 46,114, 59, 10, 9,114,101,115,117,108,116, 46,103, 32, 61, 32, 99,111,108,111,114, 46,103, - 59, 10, 9,114,101,115,117,108,116, 46, 98, 32, 61, 32, 99,111,108,111,114, 46, 98, 59, 10, 9,114,101,115,117,108,116, 46, 97, - 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,118,101,108,118,101,116, - 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,115,105,103,109, 97, 44, 32,118,101, 99, 51, 32, 78, - 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,110,111,100,101, 95, 98,115,100,102, 95, -100,105,102,102,117,115,101, 40, 99,111,108,111,114, 44, 32, 48, 46, 48, 44, 32, 78, 44, 32,114,101,115,117,108,116, 41, 59, 10, -125, 10, 10, 47, 42, 32,101,109,105,115,115,105,111,110, 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95,101,109,105, -115,115,105,111,110, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,115,116,114,101,110,103,116,104, - 44, 32,118,101, 99, 51, 32, 78, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,114,101, -115,117,108,116, 32, 61, 32, 99,111,108,111,114, 42,115,116,114,101,110,103,116,104, 59, 10,125, 10, 10, 47, 42, 32, 99,108,111, -115,117,114,101,115, 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95,109,105,120, 95,115,104, 97,100,101,114, 40,102, -108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32,115,104, 97,100,101,114, 49, 44, 32,118,101, 99, 52, 32,115,104, 97, -100,101,114, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,115,104, 97,100,101,114, 41, 10,123, 10, 9,115,104, 97,100,101,114, - 32, 61, 32,109,105,120, 40,115,104, 97,100,101,114, 49, 44, 32,115,104, 97,100,101,114, 50, 44, 32,102, 97, 99, 41, 59, 10,125, - 10, 10,118,111,105,100, 32,110,111,100,101, 95, 97,100,100, 95,115,104, 97,100,101,114, 40,118,101, 99, 52, 32,115,104, 97,100, -101,114, 49, 44, 32,118,101, 99, 52, 32,115,104, 97,100,101,114, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,115,104, 97,100, -101,114, 41, 10,123, 10, 9,115,104, 97,100,101,114, 32, 61, 32,115,104, 97,100,101,114, 49, 32, 43, 32,115,104, 97,100,101,114, - 50, 59, 10,125, 10, 10, 47, 42, 32,102,114,101,115,110,101,108, 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95,102, -114,101,115,110,101,108, 40,102,108,111, 97,116, 32,105,111,114, 44, 32,118,101, 99, 51, 32, 78, 44, 32,118,101, 99, 51, 32, 73, - 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,102,108,111, 97,116, 32,101,116, 97, - 32, 61, 32,109, 97,120, 40,105,111,114, 44, 32, 48, 46, 48, 48, 48, 48, 49, 41, 59, 10, 9,114,101,115,117,108,116, 32, 61, 32, -102,114,101,115,110,101,108, 95,100,105,101,108,101, 99,116,114,105, 99, 40, 73, 44, 32, 78, 44, 32,101,116, 97, 41, 59, 32, 47, - 47, 98, 97, 99,107,102, 97, 99,105,110,103, 40, 41, 63, 32, 49, 46, 48, 47,101,116, 97, 58, 32,101,116, 97, 41, 59, 10,125, 10, - 10, 47, 42, 32,103,101,111,109,101,116,114,121, 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95,103,101,111,109,101, -116,114,121, 40,118,101, 99, 51, 32, 73, 44, 32,118,101, 99, 51, 32, 78, 44, 32,109, 97,116, 52, 32,116,111,119,111,114,108,100, - 44, 10, 9,111,117,116, 32,118,101, 99, 51, 32,112,111,115,105,116,105,111,110, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110, -111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,116, 97,110,103,101,110,116, 44, 10, 9,111,117,116, 32,118,101, - 99, 51, 32,116,114,117,101, 95,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,109,105,110, -103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,112, 97,114, 97,109,101,116,114,105, 99, 44, 10, 9,111,117,116, 32,102,108,111, - 97,116, 32, 98, 97, 99,107,102, 97, 99,105,110,103, 41, 10,123, 10, 9,112,111,115,105,116,105,111,110, 32, 61, 32, 40,116,111, -119,111,114,108,100, 42,118,101, 99, 52, 40, 73, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9,110,111,114,109, 97,108, - 32, 61, 32, 78, 59, 10, 9,116, 97,110,103,101,110,116, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 41, 59, 10, 9,116,114,117, -101, 95,110,111,114,109, 97,108, 32, 61, 32, 78, 59, 10, 9,105,110, 99,111,109,105,110,103, 32, 61, 32, 73, 59, 10, 9,112, 97, -114, 97,109,101,116,114,105, 99, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 41, 59, 10, 9, 98, 97, 99,107,102, 97, 99,105,110, -103, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95,116,101,120, 95, 99,111,111,114,100, 40, -118,101, 99, 51, 32, 73, 44, 32,118,101, 99, 51, 32, 78, 44, 32,109, 97,116, 52, 32,116,111,119,111,114,108,100, 44, 10, 9,118, -101, 99, 51, 32, 97,116,116,114, 95,111,114, 99,111, 44, 32,118,101, 99, 51, 32, 97,116,116,114, 95,117,118, 44, 10, 9,111,117, -116, 32,118,101, 99, 51, 32,103,101,110,101,114, 97,116,101,100, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 44, 32,111, -117,116, 32,118,101, 99, 51, 32,111, 98,106,101, 99,116, 44, 10, 9,111,117,116, 32,118,101, 99, 51, 32, 99, 97,109,101,114, 97, - 44, 32,111,117,116, 32,118,101, 99, 51, 32,119,105,110,100,111,119, 44, 32,111,117,116, 32,118,101, 99, 51, 32,114,101,102,108, -101, 99,116,105,111,110, 41, 10,123, 10, 9,103,101,110,101,114, 97,116,101,100, 32, 61, 32, 97,116,116,114, 95,111,114, 99,111, + 41, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,103,108, 97,115,115, 40,118,101, 99, 52, 32, + 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104,110,101,115,115, 44, 32,102,108,111, 97,116, 32,105,111, +114, 44, 32,118,101, 99, 51, 32, 78, 44, 32,118,101, 99, 51, 32, 73, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117, +108,116, 41, 10,123, 10, 9,110,111,100,101, 95, 98,115,100,102, 95,100,105,102,102,117,115,101, 40, 99,111,108,111,114, 44, 32, + 48, 46, 48, 44, 32, 78, 44, 32,114,101,115,117,108,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115, +100,102, 95,116,114, 97,110,115,108,117, 99,101,110,116, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,118,101, 99, 51, 32, + 78, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,110,111,100,101, 95, 98,115,100,102, + 95,100,105,102,102,117,115,101, 40, 99,111,108,111,114, 44, 32, 48, 46, 48, 44, 32, 78, 44, 32,114,101,115,117,108,116, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,116,114, 97,110,115,112, 97,114,101,110,116, 40,118, +101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9, 47, + 42, 32,116,104,105,115, 32,105,115,110, 39,116, 32,114,105,103,104,116, 32, 42, 47, 10, 9,114,101,115,117,108,116, 46,114, 32, + 61, 32, 99,111,108,111,114, 46,114, 59, 10, 9,114,101,115,117,108,116, 46,103, 32, 61, 32, 99,111,108,111,114, 46,103, 59, 10, + 9,114,101,115,117,108,116, 46, 98, 32, 61, 32, 99,111,108,111,114, 46, 98, 59, 10, 9,114,101,115,117,108,116, 46, 97, 32, 61, + 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95, 98,115,100,102, 95,118,101,108,118,101,116, 40,118, +101, 99, 52, 32, 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,115,105,103,109, 97, 44, 32,118,101, 99, 51, 32, 78, 44, 32, +111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,110,111,100,101, 95, 98,115,100,102, 95,100,105, +102,102,117,115,101, 40, 99,111,108,111,114, 44, 32, 48, 46, 48, 44, 32, 78, 44, 32,114,101,115,117,108,116, 41, 59, 10,125, 10, + 10, 47, 42, 32,101,109,105,115,115,105,111,110, 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95,101,109,105,115,115, +105,111,110, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,102,108,111, 97,116, 32,115,116,114,101,110,103,116,104, 44, 32, +118,101, 99, 51, 32, 78, 44, 32,111,117,116, 32,118,101, 99, 52, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,114,101,115,117, +108,116, 32, 61, 32, 99,111,108,111,114, 42,115,116,114,101,110,103,116,104, 59, 10,125, 10, 10, 47, 42, 32, 99,108,111,115,117, +114,101,115, 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95,109,105,120, 95,115,104, 97,100,101,114, 40,102,108,111, + 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32,115,104, 97,100,101,114, 49, 44, 32,118,101, 99, 52, 32,115,104, 97,100,101, +114, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,115,104, 97,100,101,114, 41, 10,123, 10, 9,115,104, 97,100,101,114, 32, 61, + 32,109,105,120, 40,115,104, 97,100,101,114, 49, 44, 32,115,104, 97,100,101,114, 50, 44, 32,102, 97, 99, 41, 59, 10,125, 10, 10, +118,111,105,100, 32,110,111,100,101, 95, 97,100,100, 95,115,104, 97,100,101,114, 40,118,101, 99, 52, 32,115,104, 97,100,101,114, + 49, 44, 32,118,101, 99, 52, 32,115,104, 97,100,101,114, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,115,104, 97,100,101,114, + 41, 10,123, 10, 9,115,104, 97,100,101,114, 32, 61, 32,115,104, 97,100,101,114, 49, 32, 43, 32,115,104, 97,100,101,114, 50, 59, + 10,125, 10, 10, 47, 42, 32,102,114,101,115,110,101,108, 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95,102,114,101, +115,110,101,108, 40,102,108,111, 97,116, 32,105,111,114, 44, 32,118,101, 99, 51, 32, 78, 44, 32,118,101, 99, 51, 32, 73, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,114,101,115,117,108,116, 41, 10,123, 10, 9,102,108,111, 97,116, 32,101,116, 97, 32, 61, + 32,109, 97,120, 40,105,111,114, 44, 32, 48, 46, 48, 48, 48, 48, 49, 41, 59, 10, 9,114,101,115,117,108,116, 32, 61, 32,102,114, +101,115,110,101,108, 95,100,105,101,108,101, 99,116,114,105, 99, 40, 73, 44, 32, 78, 44, 32,101,116, 97, 41, 59, 32, 47, 47, 98, + 97, 99,107,102, 97, 99,105,110,103, 40, 41, 63, 32, 49, 46, 48, 47,101,116, 97, 58, 32,101,116, 97, 41, 59, 10,125, 10, 10, 47, + 42, 32,103,101,111,109,101,116,114,121, 32, 42, 47, 10, 10,118,111,105,100, 32,110,111,100,101, 95,103,101,111,109,101,116,114, +121, 40,118,101, 99, 51, 32, 73, 44, 32,118,101, 99, 51, 32, 78, 44, 32,109, 97,116, 52, 32,116,111,119,111,114,108,100, 44, 10, + 9,111,117,116, 32,118,101, 99, 51, 32,112,111,115,105,116,105,111,110, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114, +109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,116, 97,110,103,101,110,116, 44, 10, 9,111,117,116, 32,118,101, 99, 51, + 32,116,114,117,101, 95,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,109,105,110,103, 44, + 32,111,117,116, 32,118,101, 99, 51, 32,112, 97,114, 97,109,101,116,114,105, 99, 44, 10, 9,111,117,116, 32,102,108,111, 97,116, + 32, 98, 97, 99,107,102, 97, 99,105,110,103, 41, 10,123, 10, 9,112,111,115,105,116,105,111,110, 32, 61, 32, 40,116,111,119,111, +114,108,100, 42,118,101, 99, 52, 40, 73, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9,110,111,114,109, 97,108, 32, 61, + 32, 78, 59, 10, 9,116, 97,110,103,101,110,116, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 41, 59, 10, 9,116,114,117,101, 95, +110,111,114,109, 97,108, 32, 61, 32, 78, 59, 10, 9,105,110, 99,111,109,105,110,103, 32, 61, 32, 73, 59, 10, 9,112, 97,114, 97, +109,101,116,114,105, 99, 32, 61, 32,118,101, 99, 51, 40, 48, 46, 48, 41, 59, 10, 9, 98, 97, 99,107,102, 97, 99,105,110,103, 32, + 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,100,101, 95,116,101,120, 95, 99,111,111,114,100, 40,118,101, + 99, 51, 32, 73, 44, 32,118,101, 99, 51, 32, 78, 44, 32,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,109, + 97,116, 52, 32,111, 98,105,110,118,109, 97,116, 44, 10, 9,118,101, 99, 51, 32, 97,116,116,114, 95,111,114, 99,111, 44, 32,118, +101, 99, 51, 32, 97,116,116,114, 95,117,118, 44, 10, 9,111,117,116, 32,118,101, 99, 51, 32,103,101,110,101,114, 97,116,101,100, + 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 44, 32, +111,117,116, 32,118,101, 99, 51, 32,111, 98,106,101, 99,116, 44, 10, 9,111,117,116, 32,118,101, 99, 51, 32, 99, 97,109,101,114, + 97, 44, 32,111,117,116, 32,118,101, 99, 51, 32,119,105,110,100,111,119, 44, 32,111,117,116, 32,118,101, 99, 51, 32,114,101,102, +108,101, 99,116,105,111,110, 41, 10,123, 10, 9,103,101,110,101,114, 97,116,101,100, 32, 61, 32, 97,116,116,114, 95,111,114, 99, +111, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 40,111, 98,105,110,118,109, 97,116, + 42, 40,118,105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40, 78, 44, 32, 48, 46, 48, 41, 41, 41, 46,120,121,122, 41, 59, 10, 9,117,118, 32, 61, 32, 97,116,116,114, 95,117,118, 59, 10, 9,111, 98,106,101, 99,116, 32, 61, 32, 73, 59, 10, 9, 99, 97,109,101,114, 97, 32, 61, 32, 73, 59, 10, 9,119,105,110,100,111,119, 32, 61, 32,103,108, 95, 70,114, 97,103, 67,111,111,114, 100, 46,120,121,122, 59, 10, 9,114,101,102,108,101, 99,116,105,111,110, 32, 61, 32,114,101,102,108,101, 99,116, 40, 78, 44, 32, diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c index 8f67fb585c9..aa8b7070cab 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c @@ -33,6 +33,7 @@ static bNodeSocketTemplate sh_node_tex_coord_out[]= { { SOCK_VECTOR, 0, "Generated", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 0, "UV", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 0, "Object", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 0, "Camera", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, @@ -48,7 +49,7 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), GPUN return GPU_stack_link(mat, "node_tex_coord", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), orco, mtface); + GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), orco, mtface); } /* node type definition */ From 845cb7a6eed337c82f9167d3154734dce53218b9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 19 Apr 2012 09:03:43 +0000 Subject: [PATCH 009/183] Cycles: increase SVM stack size to allow more complex node setups, did not find any slowdowns with the increased size. --- intern/cycles/kernel/svm/svm_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 7ca852a24b6..fa7c211b5f9 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -24,7 +24,7 @@ CCL_NAMESPACE_BEGIN /* Stack */ /* SVM stack has a fixed size */ -#define SVM_STACK_SIZE 64 +#define SVM_STACK_SIZE 255 /* SVM stack offsets with this value indicate that it's not on the stack */ #define SVM_STACK_INVALID 255 From 90332f69a72f66a96b2b1d6f0c3b5e260db2a647 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 20 Apr 2012 12:55:44 +0000 Subject: [PATCH 010/183] Tomato branch: "persistent" parameter for addon_utils.enable(), so that we can enable addons from a startup script and keep them enabled after loading .blend files. --- release/scripts/modules/addon_utils.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 588c10eea54..695bb8cb6b6 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -212,10 +212,13 @@ def check(module_name): loaded_state = False + if mod and getattr(mod, "__addon_persistent__", False): + loaded_default = True + return loaded_default, loaded_state -def enable(module_name, default_set=True): +def enable(module_name, default_set=True, persistent=False): """ Enables an addon by name. @@ -283,6 +286,7 @@ def enable(module_name, default_set=True): ext.module = module_name mod.__addon_enabled__ = True + mod.__addon_persistent__ = persistent if _bpy.app.debug_python: print("\taddon_utils.enable", mod.__name__) @@ -305,6 +309,7 @@ def disable(module_name, default_set=True): # the addon in the user prefs. if mod: mod.__addon_enabled__ = False + mod.__addon_persistent = False try: mod.unregister() From ea4ce9e4ea88c7374e6633c6407812af0e2e6170 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 24 Apr 2012 11:43:41 +0000 Subject: [PATCH 011/183] Cycles: centralized task scheduler for multithreading, which is basically the CPU device threading code wrapped into something reusable. Basic idea is that there is a single TaskScheduler that keeps a pool of threads, one for each core. Other places in the code can then create a TaskPool that they can drop Tasks in to be executed by the scheduler, and wait for them to complete or cancel them early. --- intern/cycles/device/device.cpp | 9 -- intern/cycles/device/device.h | 4 +- intern/cycles/device/device_cpu.cpp | 61 +++---- intern/cycles/device/device_multi.cpp | 7 +- intern/cycles/render/session.cpp | 5 + intern/cycles/util/CMakeLists.txt | 2 + intern/cycles/util/util_math.h | 105 +++++++++--- intern/cycles/util/util_task.cpp | 223 ++++++++++++++++++++++++++ intern/cycles/util/util_task.h | 122 ++++++++++++++ intern/cycles/util/util_thread.h | 127 --------------- intern/cycles/util/util_types.h | 170 ++++++++++++++++---- 11 files changed, 605 insertions(+), 230 deletions(-) create mode 100644 intern/cycles/util/util_task.cpp create mode 100644 intern/cycles/util/util_task.h diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index cceec8b8e5c..42dda1180c7 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -58,15 +58,6 @@ void DeviceTask::split_max_size(list& tasks, int max_size) split(tasks, num); } -void DeviceTask::split(ThreadQueue& queue, int num) -{ - list tasks; - split(tasks, num); - - foreach(DeviceTask& task, tasks) - queue.push(task); -} - void DeviceTask::split(list& tasks, int num) { if(type == SHADER) { diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index af2567498d9..87f255e54e7 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -25,6 +25,7 @@ #include "util_list.h" #include "util_string.h" +#include "util_task.h" #include "util_thread.h" #include "util_types.h" #include "util_vector.h" @@ -66,7 +67,7 @@ public: /* Device Task */ -class DeviceTask { +class DeviceTask : public Task { public: typedef enum { PATH_TRACE, TONEMAP, SHADER } Type; Type type; @@ -87,7 +88,6 @@ public: DeviceTask(Type type = PATH_TRACE); void split(list& tasks, int num); - void split(ThreadQueue& tasks, int num); void split_max_size(list& tasks, int max_size); }; diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index da977ed8472..ec84047c44f 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -40,35 +40,21 @@ CCL_NAMESPACE_BEGIN class CPUDevice : public Device { public: - vector threads; - ThreadQueue tasks; + TaskPool task_pool; KernelGlobals *kg; CPUDevice(int threads_num) + : task_pool(function_bind(&CPUDevice::thread_run, this, _1, _2)) { kg = kernel_globals_create(); /* do now to avoid thread issues */ system_cpu_support_optimized(); - - if(threads_num == 0) - threads_num = system_cpu_thread_count(); - - threads.resize(threads_num); - - for(size_t i = 0; i < threads.size(); i++) - threads[i] = new thread(function_bind(&CPUDevice::thread_run, this, i)); } ~CPUDevice() { - tasks.stop(); - - foreach(thread *t, threads) { - t->join(); - delete t; - } - + task_pool.stop(); kernel_globals_free(kg); } @@ -127,25 +113,21 @@ public: #endif } - void thread_run(int t) + void thread_run(Task *task_, int thread_id) { - DeviceTask task; + DeviceTask *task = (DeviceTask*)task_; - while(tasks.worker_wait_pop(task)) { - if(task.type == DeviceTask::PATH_TRACE) - thread_path_trace(task); - else if(task.type == DeviceTask::TONEMAP) - thread_tonemap(task); - else if(task.type == DeviceTask::SHADER) - thread_shader(task); - - tasks.worker_done(); - } + if(task->type == DeviceTask::PATH_TRACE) + thread_path_trace(*task); + else if(task->type == DeviceTask::TONEMAP) + thread_tonemap(*task); + else if(task->type == DeviceTask::SHADER) + thread_shader(*task); } void thread_path_trace(DeviceTask& task) { - if(tasks.worker_cancel()) + if(task_pool.cancelled()) return; #ifdef WITH_OSL @@ -160,7 +142,7 @@ public: kernel_cpu_optimized_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state, task.sample, x, y, task.offset, task.stride); - if(tasks.worker_cancel()) + if(task_pool.cancelled()) break; } } @@ -172,7 +154,7 @@ public: kernel_cpu_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state, task.sample, x, y, task.offset, task.stride); - if(tasks.worker_cancel()) + if(task_pool.cancelled()) break; } } @@ -214,7 +196,7 @@ public: for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) { kernel_cpu_optimized_shader(kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); - if(tasks.worker_cancel()) + if(task_pool.cancelled()) break; } } @@ -224,7 +206,7 @@ public: for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) { kernel_cpu_shader(kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); - if(tasks.worker_cancel()) + if(task_pool.cancelled()) break; } } @@ -239,17 +221,22 @@ public: { /* split task into smaller ones, more than number of threads for uneven workloads where some parts of the image render slower than others */ - task.split(tasks, threads.size()*10); + list tasks; + + task.split(tasks, TaskScheduler::num_threads()*10); + + foreach(DeviceTask& task, tasks) + task_pool.push(new DeviceTask(task)); } void task_wait() { - tasks.wait_done(); + task_pool.wait(); } void task_cancel() { - tasks.cancel(); + task_pool.cancel(); } }; diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 1f69f2c53fa..9f7d65e640b 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -257,13 +257,14 @@ public: void task_add(DeviceTask& task) { - ThreadQueue tasks; + list tasks; task.split(tasks, devices.size()); foreach(SubDevice& sub, devices) { - DeviceTask subtask; + if(!tasks.empty()) { + DeviceTask subtask = tasks.front(); + tasks.pop_front(); - if(tasks.worker_wait_pop(subtask)) { if(task.buffer) subtask.buffer = sub.ptr_map[task.buffer]; if(task.rng_state) subtask.rng_state = sub.ptr_map[task.rng_state]; if(task.rgba) subtask.rgba = sub.ptr_map[task.rgba]; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 676f42be790..34a0c0ff877 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -27,6 +27,7 @@ #include "util_foreach.h" #include "util_function.h" +#include "util_task.h" #include "util_time.h" CCL_NAMESPACE_BEGIN @@ -37,6 +38,8 @@ Session::Session(const SessionParams& params_) { device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background); + TaskScheduler::init(params.threads); + device = Device::create(params.device, params.background, params.threads); buffers = new RenderBuffers(device); display = new DisplayBuffer(device); @@ -88,6 +91,8 @@ Session::~Session() delete display; delete scene; delete device; + + TaskScheduler::exit(); } void Session::start() diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index 9182ee4cbe1..87bd84b4e0f 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -15,6 +15,7 @@ set(SRC util_path.cpp util_string.cpp util_system.cpp + util_task.cpp util_time.cpp util_transform.cpp ) @@ -50,6 +51,7 @@ set(SRC_HEADERS util_set.h util_string.h util_system.h + util_task.h util_thread.h util_time.h util_transform.h diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 019dede07fa..8768c798d16 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -578,51 +578,43 @@ __device_inline float average(const float4& a) __device_inline float4 operator-(const float4& a) { - float4 r = {-a.x, -a.y, -a.z, -a.w}; - return r; + return make_float4(-a.x, -a.y, -a.z, -a.w); } __device_inline float4 operator*(const float4& a, const float4& b) { - float4 r = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; - return r; + return make_float4(a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w); } __device_inline float4 operator*(const float4& a, float f) { - float4 r = {a.x*f, a.y*f, a.z*f, a.w*f}; - return r; + return make_float4(a.x*f, a.y*f, a.z*f, a.w*f); } __device_inline float4 operator*(float f, const float4& a) { - float4 r = {a.x*f, a.y*f, a.z*f, a.w*f}; - return r; + return make_float4(a.x*f, a.y*f, a.z*f, a.w*f); } __device_inline float4 operator/(const float4& a, float f) { float invf = 1.0f/f; - float4 r = {a.x*invf, a.y*invf, a.z*invf, a.w*invf}; - return r; + return make_float4(a.x*invf, a.y*invf, a.z*invf, a.w*invf); } __device_inline float4 operator/(const float4& a, const float4& b) { - float4 r = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; - return r; + return make_float4(a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w); } __device_inline float4 operator+(const float4& a, const float4& b) { - float4 r = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; - return r; + return make_float4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w); } __device_inline float4 operator-(const float4& a, const float4& b) { - float4 r = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; - return r; + return make_float4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w); } __device_inline float4 operator+=(float4& a, const float4& b) @@ -653,6 +645,21 @@ __device_inline float4 operator/=(float4& a, float f) return a; } +__device_inline int4 operator<(const float4& a, const float4& b) +{ + return make_int4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w); +} + +__device_inline int4 operator<=(const float4& a, const float4& b) +{ + return make_int4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w); +} + +__device_inline bool operator==(const float4 a, const float4 b) +{ + return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w); +} + __device_inline float dot(const float4& a, const float4& b) { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; @@ -660,8 +667,7 @@ __device_inline float dot(const float4& a, const float4& b) __device_inline float4 cross(const float4& a, const float4& b) { - float4 r = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x, 0.0f}; - return r; + return make_float4(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x, 0.0f); } __device_inline float4 min(float4 a, float4 b) @@ -674,6 +680,31 @@ __device_inline float4 max(float4 a, float4 b) return make_float4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w)); } +__device_inline float4 select(const int4& mask, const float4& a, const float4& b) +{ + return make_float4((mask.x)? a.x: b.x, (mask.y)? a.y: b.y, (mask.z)? a.z: b.z, (mask.w)? a.w: b.w); +} + +__device_inline float4 reduce_min(const float4& a) +{ + return make_float4(min(min(a.x, a.y), min(a.z, a.w))); +} + +__device_inline float4 reduce_max(const float4& a) +{ + return make_float4(max(max(a.x, a.y), max(a.z, a.w))); +} + +__device_inline float4 reduce_add(const float4& a) +{ + return make_float4((a.x + a.y) + (a.z + a.w)); +} + +__device_inline float3 rcp(const float3& a) +{ + return make_float3(1.0f/a.x, 1.0f/a.y, 1.0f/a.z); +} + #endif #ifndef __KERNEL_GPU__ @@ -691,20 +722,17 @@ __device_inline void print_float4(const char *label, const float4& a) __device_inline int3 max(int3 a, int3 b) { - int3 r = {max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)}; - return r; + return make_int3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); } __device_inline int3 clamp(const int3& a, int mn, int mx) { - int3 r = {clamp(a.x, mn, mx), clamp(a.y, mn, mx), clamp(a.z, mn, mx)}; - return r; + return make_int3(clamp(a.x, mn, mx), clamp(a.y, mn, mx), clamp(a.z, mn, mx)); } __device_inline int3 clamp(const int3& a, int3& mn, int mx) { - int3 r = {clamp(a.x, mn.x, mx), clamp(a.y, mn.y, mx), clamp(a.z, mn.z, mx)}; - return r; + return make_int3(clamp(a.x, mn.x, mx), clamp(a.y, mn.y, mx), clamp(a.z, mn.z, mx)); } #endif @@ -731,6 +759,35 @@ __device_inline int4 operator>=(float4 a, float4 b) #ifndef __KERNEL_GPU__ +__device_inline int4 operator+(const int4& a, const int4& b) +{ + return make_int4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w); +} + +__device_inline int4 operator+=(int4& a, const int4& b) +{ + a.x += b.x; + a.y += b.y; + a.z += b.z; + a.w += b.w; + return a; +} + +__device_inline int4 operator>>(const int4& a, int i) +{ + return make_int4(a.x >> i, a.y >> i, a.z >> i, a.w >> i); +} + +__device_inline int4 clamp(const int4& a, const int4& mn, const int4& mx) +{ + return make_int4(clamp(a.x, mn.x, mx.x), clamp(a.y, mn.y, mx.y), clamp(a.z, mn.z, mx.z), clamp(a.w, mn.w, mx.w)); +} + +__device_inline int4 select(const int4& mask, const int4& a, const int4& b) +{ + return make_int4((mask.x)? a.x: b.x, (mask.y)? a.y: b.y, (mask.z)? a.z: b.z, (mask.w)? a.w: b.w); +} + __device_inline void print_int4(const char *label, const int4& a) { printf("%s: %d %d %d %d\n", label, a.x, a.y, a.z, a.w); diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp new file mode 100644 index 00000000000..6da9a70ec0c --- /dev/null +++ b/intern/cycles/util/util_task.cpp @@ -0,0 +1,223 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "util_debug.h" +#include "util_foreach.h" +#include "util_system.h" +#include "util_task.h" + +CCL_NAMESPACE_BEGIN + +/* Task Pool */ + +TaskPool::TaskPool(const TaskRunFunction& run_) +{ + num = 0; + num_done = 0; + + do_cancel = false; + + run = run_; +} + +TaskPool::~TaskPool() +{ + stop(); +} + +void TaskPool::push(Task *task, bool front) +{ + TaskScheduler::Entry entry; + + entry.task = task; + entry.pool = this; + + TaskScheduler::push(entry, front); +} + +void TaskPool::wait() +{ + thread_scoped_lock lock(done_mutex); + + while(num_done != num) + done_cond.wait(lock); +} + +void TaskPool::cancel() +{ + TaskScheduler::clear(this); + + do_cancel = true; + wait(); + do_cancel = false; +} + +void TaskPool::stop() +{ + TaskScheduler::clear(this); + + assert(num_done == num); +} + +bool TaskPool::cancelled() +{ + return do_cancel; +} + +void TaskPool::done_increase(int done) +{ + done_mutex.lock(); + num_done += done; + done_mutex.unlock(); + + assert(num_done <= num); + done_cond.notify_all(); +} + +/* Task Scheduler */ + +thread_mutex TaskScheduler::mutex; +int TaskScheduler::users = 0; +vector TaskScheduler::threads; +volatile bool TaskScheduler::do_exit = false; + +list TaskScheduler::queue; +thread_mutex TaskScheduler::queue_mutex; +thread_condition_variable TaskScheduler::queue_cond; + +void TaskScheduler::init(int num_threads) +{ + thread_scoped_lock lock(mutex); + + /* multiple cycles instances can use this task scheduler, sharing the same + threads, so we keep track of the number of users. */ + if(users == 0) { + do_exit = false; + + /* launch threads that will be waiting for work */ + if(num_threads == 0) + num_threads = system_cpu_thread_count(); + + threads.resize(num_threads); + + for(size_t i = 0; i < threads.size(); i++) + threads[i] = new thread(function_bind(&TaskScheduler::thread_run, i)); + } + + users++; +} + +void TaskScheduler::exit() +{ + thread_scoped_lock lock(mutex); + + users--; + + if(users == 0) { + /* stop all waiting threads */ + do_exit = true; + TaskScheduler::queue_cond.notify_all(); + + /* delete threads */ + foreach(thread *t, threads) { + t->join(); + delete t; + } + + threads.clear(); + } +} + +bool TaskScheduler::thread_wait_pop(Entry& entry) +{ + thread_scoped_lock lock(queue_mutex); + + while(queue.empty() && !do_exit) + queue_cond.wait(lock); + + if(queue.empty()) { + assert(do_exit); + return false; + } + + entry = queue.front(); + queue.pop_front(); + + return true; +} + +void TaskScheduler::thread_run(int thread_id) +{ + Entry entry; + + /* todo: test affinity/denormal mask */ + + /* keep popping off tasks */ + while(thread_wait_pop(entry)) { + /* run task */ + entry.pool->run(entry.task, thread_id); + + /* delete task */ + delete entry.task; + + /* notify pool task was done */ + entry.pool->done_increase(1); + } +} + +void TaskScheduler::push(Entry& entry, bool front) +{ + /* add entry to queue */ + TaskScheduler::queue_mutex.lock(); + if(front) + TaskScheduler::queue.push_front(entry); + else + TaskScheduler::queue.push_back(entry); + entry.pool->num++; + TaskScheduler::queue_mutex.unlock(); + + TaskScheduler::queue_cond.notify_one(); +} + +void TaskScheduler::clear(TaskPool *pool) +{ + thread_scoped_lock lock(TaskScheduler::queue_mutex); + + /* erase all tasks from this pool from the queue */ + list::iterator it = TaskScheduler::queue.begin(); + int done = 0; + + while(it != TaskScheduler::queue.end()) { + TaskScheduler::Entry& entry = *it; + + if(entry.pool == pool) { + done++; + delete entry.task; + + it = TaskScheduler::queue.erase(it); + } + else + it++; + } + + /* notify done */ + pool->done_increase(done); +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h new file mode 100644 index 00000000000..acdb2cb50a2 --- /dev/null +++ b/intern/cycles/util/util_task.h @@ -0,0 +1,122 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UTIL_TASK_H__ +#define __UTIL_TASK_H__ + +#include "util_list.h" +#include "util_thread.h" +#include "util_vector.h" + +CCL_NAMESPACE_BEGIN + +class Task; +class TaskPool; +class TaskScheduler; + +typedef boost::function TaskRunFunction; + +/* Task + * + * Base class for tasks to be executed in threads. */ + +class Task +{ +public: + Task() {}; + virtual ~Task() {} +}; + +/* Task Pool + * + * Pool of tasks that will be executed by the central TaskScheduler.For each + * pool, we can wait for all tasks to be done, or cancel them before they are + * done. + * + * The run callback that actually executes the task may be create like this: + * function_bind(&MyClass::task_execute, this, _1, _2) */ + +class TaskPool +{ +public: + TaskPool(const TaskRunFunction& run); + ~TaskPool(); + + void push(Task *task, bool front = false); + + void wait(); /* wait until all tasks are done */ + void cancel(); /* cancel all tasks, keep worker threads running */ + void stop(); /* stop all worker threads */ + + bool cancelled(); /* for worker threads, test if cancelled */ + +protected: + friend class TaskScheduler; + + void done_increase(int done); + + TaskRunFunction run; + + thread_mutex done_mutex; + thread_condition_variable done_cond; + + volatile int num, num_done; + volatile bool do_cancel; +}; + +/* Task Scheduler + * + * Central scheduler that holds running threads ready to execute tasks. A singe + * queue holds the task from all pools. */ + +class TaskScheduler +{ +public: + static void init(int num_threads = 0); + static void exit(); + + static int num_threads() { return threads.size(); } + +protected: + friend class TaskPool; + + struct Entry { + Task *task; + TaskPool *pool; + }; + + static thread_mutex mutex; + static int users; + static vector threads; + static volatile bool do_exit; + + static list queue; + static thread_mutex queue_mutex; + static thread_condition_variable queue_cond; + + static void thread_run(int thread_id); + static bool thread_wait_pop(Entry& entry); + + static void push(Entry& entry, bool front); + static void clear(TaskPool *pool); +}; + +CCL_NAMESPACE_END + +#endif + diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h index 6836be203f5..3d15b342fe5 100644 --- a/intern/cycles/util/util_thread.h +++ b/intern/cycles/util/util_thread.h @@ -69,133 +69,6 @@ protected: bool joined; }; -/* Thread Safe Queue to pass tasks from one thread to another. Tasks should be - * pushed into the queue, while the worker thread waits to pop the next task - * off the queue. Once all tasks are into the queue, calling stop() will stop - * the worker threads from waiting for more tasks once all tasks are done. */ - -template class ThreadQueue -{ -public: - ThreadQueue() - { - tot = 0; - tot_done = 0; - do_stop = false; - do_cancel = false; - } - - /* Main thread functions */ - - /* push a task to be executed */ - void push(const T& value) - { - thread_scoped_lock lock(queue_mutex); - queue.push(value); - tot++; - lock.unlock(); - - queue_cond.notify_one(); - } - - /* wait until all tasks are done */ - void wait_done() - { - thread_scoped_lock lock(done_mutex); - - while(tot_done != tot) - done_cond.wait(lock); - } - - /* stop all worker threads */ - void stop() - { - clear(); - do_stop = true; - queue_cond.notify_all(); - } - - /* cancel all tasks, but keep worker threads running */ - void cancel() - { - clear(); - do_cancel = true; - wait_done(); - do_cancel = false; - } - - /* Worker thread functions - * - * while(queue.worker_wait_pop(task)) { - * for(..) { - * ... do work ... - * - * if(queue.worker_cancel()) - * break; - * } - * - * queue.worker_done(); - * } - */ - - bool worker_wait_pop(T& value) - { - thread_scoped_lock lock(queue_mutex); - - while(queue.empty() && !do_stop) - queue_cond.wait(lock); - - if(queue.empty()) - return false; - - value = queue.front(); - queue.pop(); - - return true; - } - - void worker_done() - { - thread_scoped_lock lock(done_mutex); - tot_done++; - lock.unlock(); - - assert(tot_done <= tot); - - done_cond.notify_all(); - } - - bool worker_cancel() - { - return do_cancel; - } - -protected: - void clear() - { - thread_scoped_lock lock(queue_mutex); - - while(!queue.empty()) { - thread_scoped_lock done_lock(done_mutex); - tot_done++; - done_lock.unlock(); - - queue.pop(); - } - - done_cond.notify_all(); - } - - std::queue queue; - thread_mutex queue_mutex; - thread_mutex done_mutex; - thread_condition_variable queue_cond; - thread_condition_variable done_cond; - volatile bool do_stop; - volatile bool do_cancel; - volatile int tot, tot_done; -}; - /* Thread Local Storage * * Boost implementation is a bit slow, and Mac OS X __thread is not supported diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index efdda98571a..b6c57e3eb6e 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -36,23 +36,29 @@ #define __shared #define __constant -#ifdef __GNUC__ -#define __device_inline static inline __attribute__((always_inline)) -#else +#ifdef __WIN32__ #define __device_inline static __forceinline +#define __align(...) __declspec(align(__VA_ARGS__)) +#else +#define __device_inline static inline __attribute__((always_inline)) +#define __forceinline inline __attribute__((always_inline)) +#define __align(...) __attribute__((aligned(__VA_ARGS__))) #endif #endif /* SIMD Types */ -/* not needed yet, will be for qbvh -#ifndef __KERNEL_GPU__ +/* not enabled yet, just testing */ +#if 0 +#define __KERNEL_SSE__ +#ifdef __KERNEL_SSE__ #include #include -#endif*/ +#endif +#endif #ifndef _WIN32 #ifndef __KERNEL_GPU__ @@ -133,15 +139,31 @@ struct int2 { int& operator[](int i) { return *(&x + i); } }; +#ifdef __KERNEL_SSE__ +struct __align(16) int3 { + union { + __m128i m128; + struct { int x, y, z, w; }; + }; +#else struct int3 { - int x, y, z; + int x, y, z, w; +#endif int operator[](int i) const { return *(&x + i); } int& operator[](int i) { return *(&x + i); } }; +#ifdef __KERNEL_SSE__ +struct __align(16) int4 { + union { + __m128i m128; + struct { int x, y, z, w; }; + }; +#else struct int4 { int x, y, z, w; +#endif int operator[](int i) const { return *(&x + i); } int& operator[](int i) { return *(&x + i); } @@ -175,19 +197,31 @@ struct float2 { float& operator[](int i) { return *(&x + i); } }; +#ifdef __KERNEL_SSE__ +struct __align(16) float3 { + union { + __m128 m128; + struct { float x, y, z, w; }; + }; +#else struct float3 { - float x, y, z; - -#ifdef WITH_OPENCL - float w; + float x, y, z, w; #endif float operator[](int i) const { return *(&x + i); } float& operator[](int i) { return *(&x + i); } }; +#ifdef __KERNEL_SSE__ +struct __align(16) float4 { + union { + __m128 m128; + struct { float x, y, z, w; }; + }; +#else struct float4 { float x, y, z, w; +#endif float operator[](int i) const { return *(&x + i); } float& operator[](int i) { return *(&x + i); } @@ -201,87 +235,167 @@ struct float4 { * * OpenCL does not support C++ class, so we use these instead. */ -__device uchar2 make_uchar2(uchar x, uchar y) +__device_inline uchar2 make_uchar2(uchar x, uchar y) { uchar2 a = {x, y}; return a; } -__device uchar3 make_uchar3(uchar x, uchar y, uchar z) +__device_inline uchar3 make_uchar3(uchar x, uchar y, uchar z) { uchar3 a = {x, y, z}; return a; } -__device uchar4 make_uchar4(uchar x, uchar y, uchar z, uchar w) +__device_inline uchar4 make_uchar4(uchar x, uchar y, uchar z, uchar w) { uchar4 a = {x, y, z, w}; return a; } -__device int2 make_int2(int x, int y) +__device_inline int2 make_int2(int x, int y) { int2 a = {x, y}; return a; } -__device int3 make_int3(int x, int y, int z) +__device_inline int3 make_int3(int x, int y, int z) { - int3 a = {x, y, z}; +#ifdef __KERNEL_SSE__ + int3 a; + a.m128 = _mm_set_epi32(0, z, y, x); +#else + int3 a = {x, y, z, 0}; +#endif + return a; } -__device int4 make_int4(int x, int y, int z, int w) +__device_inline int4 make_int4(int x, int y, int z, int w) { +#ifdef __KERNEL_SSE__ + int4 a; + a.m128 = _mm_set_epi32(w, z, y, x); +#else int4 a = {x, y, z, w}; +#endif + return a; } -__device uint2 make_uint2(uint x, uint y) +__device_inline uint2 make_uint2(uint x, uint y) { uint2 a = {x, y}; return a; } -__device uint3 make_uint3(uint x, uint y, uint z) +__device_inline uint3 make_uint3(uint x, uint y, uint z) { uint3 a = {x, y, z}; return a; } -__device uint4 make_uint4(uint x, uint y, uint z, uint w) +__device_inline uint4 make_uint4(uint x, uint y, uint z, uint w) { uint4 a = {x, y, z, w}; return a; } -__device float2 make_float2(float x, float y) +__device_inline float2 make_float2(float x, float y) { float2 a = {x, y}; return a; } -__device float3 make_float3(float x, float y, float z) +__device_inline float3 make_float3(float x, float y, float z) { -#ifdef WITH_OPENCL - float3 a = {x, y, z, 0.0f}; +#ifdef __KERNEL_SSE__ + float3 a; + a.m128 = _mm_set_ps(0.0f, z, y, x); #else - float3 a = {x, y, z}; + float3 a = {x, y, z, 0.0f}; #endif + return a; } -__device float4 make_float4(float x, float y, float z, float w) +__device_inline float4 make_float4(float x, float y, float z, float w) { +#ifdef __KERNEL_SSE__ + float4 a; + a.m128 = _mm_set_ps(w, z, y, x); +#else float4 a = {x, y, z, w}; +#endif + return a; } -__device int align_up(int offset, int alignment) +__device_inline int align_up(int offset, int alignment) { return (offset + alignment - 1) & ~(alignment - 1); } +__device_inline int4 make_int4(int i) +{ +#ifdef __KERNEL_SSE__ + int4 a; + a.m128 = _mm_set1_epi32(i); +#else + int4 a = {i, i, i, i}; +#endif + + return a; +} + +__device_inline float3 make_float3(float f) +{ +#ifdef __KERNEL_SSE__ + float3 a; + a.m128 = _mm_set1_ps(f); +#else + float3 a = {f, f, f, f}; +#endif + + return a; +} + +__device_inline float4 make_float4(float f) +{ +#ifdef __KERNEL_SSE__ + float4 a; + a.m128 = _mm_set1_ps(f); +#else + float4 a = {f, f, f, f}; +#endif + + return a; +} + +__device_inline float4 make_float4(const int4& i) +{ +#ifdef __KERNEL_SSE__ + float4 a; + a.m128 = _mm_cvtepi32_ps(i.m128); +#else + float4 a = {(float)i.x, (float)i.y, (float)i.z, (float)i.w}; +#endif + + return a; +} + +__device_inline int4 make_int4(const float3& f) +{ +#ifdef __KERNEL_SSE__ + int4 a; + a.m128 = _mm_cvtps_epi32(f.m128); +#else + int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w}; +#endif + + return a; +} + #endif CCL_NAMESPACE_END From 764432ac930e0e62ca2e7ddd5228a2be4867e797 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 24 Apr 2012 11:52:58 +0000 Subject: [PATCH 012/183] Cycles: BVH build time optimizations: * BVH building was multithreaded. Not all building is multithreaded, packing and the initial bounding/splitting is still single threaded, but recursive splitting is, which was the main bottleneck. * Object splitting now uses binning rather than sorting of all elements, using code from the Embree raytracer from Intel. http://software.intel.com/en-us/articles/embree-photo-realistic-ray-tracing-kernels/ * Other small changes to avoid allocations, pack memory more tightly, avoid some unnecessary operations, ... These optimizations do not work yet when Spatial Splits are enabled, for that more work is needed. There's also other optimizations still needed, in particular for the case of many low poly objects, the packing step and node memory allocation. BVH raytracing time should remain about the same, but BVH build time should be significantly reduced, test here show speedup of about 5x to 10x on a dual core and 5x to 25x on an 8-core machine, depending on the scene. --- intern/cycles/bvh/CMakeLists.txt | 4 + intern/cycles/bvh/bvh.cpp | 4 +- intern/cycles/bvh/bvh_binning.cpp | 219 ++++++++++ intern/cycles/bvh/bvh_binning.h | 86 ++++ intern/cycles/bvh/bvh_build.cpp | 648 +++++++++++++---------------- intern/cycles/bvh/bvh_build.h | 104 ++--- intern/cycles/bvh/bvh_node.cpp | 22 +- intern/cycles/bvh/bvh_node.h | 18 +- intern/cycles/bvh/bvh_params.h | 91 +++- intern/cycles/bvh/bvh_sort.cpp | 16 +- intern/cycles/bvh/bvh_sort.h | 2 +- intern/cycles/bvh/bvh_split.cpp | 293 +++++++++++++ intern/cycles/bvh/bvh_split.h | 110 +++++ intern/cycles/render/mesh.cpp | 7 +- intern/cycles/render/object.cpp | 1 + intern/cycles/subd/subd_patch.cpp | 12 +- intern/cycles/util/util_boundbox.h | 87 +++- 17 files changed, 1252 insertions(+), 472 deletions(-) create mode 100644 intern/cycles/bvh/bvh_binning.cpp create mode 100644 intern/cycles/bvh/bvh_binning.h create mode 100644 intern/cycles/bvh/bvh_split.cpp create mode 100644 intern/cycles/bvh/bvh_split.h diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt index decc576fe51..131a7a1f750 100644 --- a/intern/cycles/bvh/CMakeLists.txt +++ b/intern/cycles/bvh/CMakeLists.txt @@ -10,17 +10,21 @@ set(INC set(SRC bvh.cpp + bvh_binning.cpp bvh_build.cpp bvh_node.cpp bvh_sort.cpp + bvh_split.cpp ) set(SRC_HEADERS bvh.h + bvh_binning.h bvh_build.h bvh_node.h bvh_params.h bvh_sort.h + bvh_split.h ) include_directories(${INC}) diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index c9bfa964332..15695dddf45 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -530,7 +530,7 @@ void RegularBVH::refit_nodes() { assert(!params.top_level); - BoundBox bbox; + BoundBox bbox = BoundBox::empty; uint visibility = 0; refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility); } @@ -572,7 +572,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility } else { /* refit inner node, set bbox from children */ - BoundBox bbox0, bbox1; + BoundBox bbox0 = BoundBox::empty, bbox1 = BoundBox::empty; uint visibility0 = 0, visibility1 = 0; refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0, visibility0); diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp new file mode 100644 index 00000000000..def5309e551 --- /dev/null +++ b/intern/cycles/bvh/bvh_binning.cpp @@ -0,0 +1,219 @@ +/* + * Adapted from code copyright 2009-2011 Intel Corporation + * Modifications Copyright 2012, Blender Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bvh_binning.h" + +#include "util_algorithm.h" +#include "util_boundbox.h" +#include "util_types.h" + +CCL_NAMESPACE_BEGIN + +/* SSE replacements */ + +__forceinline void prefetch_L1 (const void* ptr) { } +__forceinline void prefetch_L2 (const void* ptr) { } +__forceinline void prefetch_L3 (const void* ptr) { } +__forceinline void prefetch_NTA(const void* ptr) { } + +template __forceinline float extract(const int4& b) +{ return b[src]; } +template __forceinline const float4 insert(const float4& a, const float b) +{ float4 r = a; r[dst] = b; return r; } + +__forceinline int get_best_dimension(const float4& bestSAH) +{ + // return (int)__bsf(movemask(reduce_min(bestSAH) == bestSAH)); + + float minSAH = min(bestSAH.x, min(bestSAH.y, bestSAH.z)); + + if(bestSAH.x == minSAH) return 0; + else if(bestSAH.y == minSAH) return 1; + else return 2; +} + +/* BVH Object Binning */ + +BVHObjectBinning::BVHObjectBinning(const BVHRange& job, BVHReference *prims) +: BVHRange(job), splitSAH(FLT_MAX), dim(0), pos(0) +{ + /* compute number of bins to use and precompute scaling factor for binning */ + num_bins = min(size_t(MAX_BINS), size_t(4.0f + 0.05f*size())); + scale = rcp(cent_bounds().size()) * make_float3((float)num_bins); + + /* initialize binning counter and bounds */ + BoundBox bin_bounds[MAX_BINS][4]; /* bounds for every bin in every dimension */ + int4 bin_count[MAX_BINS]; /* number of primitives mapped to bin */ + + for(size_t i = 0; i < num_bins; i++) { + bin_count[i] = make_int4(0); + bin_bounds[i][0] = bin_bounds[i][1] = bin_bounds[i][2] = BoundBox::empty; + } + + /* map geometry to bins, unrolled once */ + { + ssize_t i; + + for(i = 0; i < ssize_t(size()) - 1; i += 2) { + prefetch_L2(&prims[start() + i + 8]); + + /* map even and odd primitive to bin */ + BVHReference prim0 = prims[start() + i + 0]; + BVHReference prim1 = prims[start() + i + 1]; + + int4 bin0 = get_bin(prim0.bounds()); + int4 bin1 = get_bin(prim1.bounds()); + + /* increase bounds for bins for even primitive */ + int b00 = extract<0>(bin0); bin_count[b00][0]++; bin_bounds[b00][0].grow(prim0.bounds()); + int b01 = extract<1>(bin0); bin_count[b01][1]++; bin_bounds[b01][1].grow(prim0.bounds()); + int b02 = extract<2>(bin0); bin_count[b02][2]++; bin_bounds[b02][2].grow(prim0.bounds()); + + /* increase bounds of bins for odd primitive */ + int b10 = extract<0>(bin1); bin_count[b10][0]++; bin_bounds[b10][0].grow(prim1.bounds()); + int b11 = extract<1>(bin1); bin_count[b11][1]++; bin_bounds[b11][1].grow(prim1.bounds()); + int b12 = extract<2>(bin1); bin_count[b12][2]++; bin_bounds[b12][2].grow(prim1.bounds()); + } + + /* for uneven number of primitives */ + if(i < ssize_t(size())) { + /* map primitive to bin */ + BVHReference prim0 = prims[start() + i]; + int4 bin0 = get_bin(prim0.bounds()); + + /* increase bounds of bins */ + int b00 = extract<0>(bin0); bin_count[b00][0]++; bin_bounds[b00][0].grow(prim0.bounds()); + int b01 = extract<1>(bin0); bin_count[b01][1]++; bin_bounds[b01][1].grow(prim0.bounds()); + int b02 = extract<2>(bin0); bin_count[b02][2]++; bin_bounds[b02][2].grow(prim0.bounds()); + } + } + + /* sweep from right to left and compute parallel prefix of merged bounds */ + float4 r_area[MAX_BINS]; /* area of bounds of primitives on the right */ + float4 r_count[MAX_BINS]; /* number of primitives on the right */ + int4 count = make_int4(0); + + BoundBox bx = BoundBox::empty; + BoundBox by = BoundBox::empty; + BoundBox bz = BoundBox::empty; + + for(size_t i = num_bins - 1; i > 0; i--) { + count = count + bin_count[i]; + r_count[i] = blocks(count); + + bx = merge(bx,bin_bounds[i][0]); r_area[i][0] = bx.half_area(); + by = merge(by,bin_bounds[i][1]); r_area[i][1] = by.half_area(); + bz = merge(bz,bin_bounds[i][2]); r_area[i][2] = bz.half_area(); + } + + /* sweep from left to right and compute SAH */ + int4 ii = make_int4(1); + float4 bestSAH = make_float4(FLT_MAX); + int4 bestSplit = make_int4(-1); + + count = make_int4(0); + + bx = BoundBox::empty; + by = BoundBox::empty; + bz = BoundBox::empty; + + for(size_t i = 1; i < num_bins; i++, ii += make_int4(1)) { + count = count + bin_count[i-1]; + + bx = merge(bx,bin_bounds[i-1][0]); float Ax = bx.half_area(); + by = merge(by,bin_bounds[i-1][1]); float Ay = by.half_area(); + bz = merge(bz,bin_bounds[i-1][2]); float Az = bz.half_area(); + + float4 lCount = blocks(count); + float4 lArea = make_float4(Ax,Ay,Az,Az); + float4 sah = lArea*lCount + r_area[i]*r_count[i]; + + bestSplit = select(sah < bestSAH,ii,bestSplit); + bestSAH = min(sah,bestSAH); + } + + int4 mask = float3_to_float4(cent_bounds().size()) <= make_float4(0.0f); + bestSAH = insert<3>(select(mask, make_float4(FLT_MAX), bestSAH), FLT_MAX); + + /* find best dimension */ + dim = get_best_dimension(bestSAH); + splitSAH = bestSAH[dim]; + pos = bestSplit[dim]; + leafSAH = bounds().half_area() * blocks(size()); +} + +void BVHObjectBinning::split(BVHReference* prims, BVHObjectBinning& left_o, BVHObjectBinning& right_o) const +{ + size_t N = size(); + + BoundBox lgeom_bounds = BoundBox::empty; + BoundBox rgeom_bounds = BoundBox::empty; + BoundBox lcent_bounds = BoundBox::empty; + BoundBox rcent_bounds = BoundBox::empty; + + ssize_t l = 0, r = N-1; + + while(l <= r) { + prefetch_L2(&prims[start() + l + 8]); + prefetch_L2(&prims[start() + r - 8]); + + BVHReference prim = prims[start() + l]; + float3 center = prim.bounds().center2(); + + if(get_bin(center)[dim] < pos) { + lgeom_bounds.grow(prim.bounds()); + lcent_bounds.grow(center); + l++; + } + else { + rgeom_bounds.grow(prim.bounds()); + rcent_bounds.grow(center); + swap(prims[start()+l],prims[start()+r]); + r--; + } + } + + /* finish */ + if(l != 0 && N-1-r != 0) { + right_o = BVHObjectBinning(BVHRange(rgeom_bounds, rcent_bounds, start() + l, N-1-r), prims); + left_o = BVHObjectBinning(BVHRange(lgeom_bounds, lcent_bounds, start(), l), prims); + return; + } + + /* object medium split if we did not make progress, can happen when all + primitives have same centroid */ + lgeom_bounds = BoundBox::empty; + rgeom_bounds = BoundBox::empty; + lcent_bounds = BoundBox::empty; + rcent_bounds = BoundBox::empty; + + for(size_t i = 0; i < N/2; i++) { + lgeom_bounds.grow(prims[start()+i].bounds()); + lcent_bounds.grow(prims[start()+i].bounds().center2()); + } + + for(size_t i = N/2; i < N; i++) { + rgeom_bounds.grow(prims[start()+i].bounds()); + rcent_bounds.grow(prims[start()+i].bounds().center2()); + } + + right_o = BVHObjectBinning(BVHRange(rgeom_bounds, rcent_bounds, start() + N/2, N/2 + N%2), prims); + left_o = BVHObjectBinning(BVHRange(lgeom_bounds, lcent_bounds, start(), N/2), prims); +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/bvh/bvh_binning.h b/intern/cycles/bvh/bvh_binning.h new file mode 100644 index 00000000000..60742157055 --- /dev/null +++ b/intern/cycles/bvh/bvh_binning.h @@ -0,0 +1,86 @@ +/* + * Adapted from code copyright 2009-2011 Intel Corporation + * Modifications Copyright 2012, Blender Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __BVH_BINNING_H__ +#define __BVH_BINNING_H__ + +#include "bvh_params.h" + +#include "util_types.h" + +CCL_NAMESPACE_BEGIN + +/* Single threaded object binner. Finds the split with the best SAH heuristic + * by testing for each dimension multiple partitionings for regular spaced + * partition locations. A partitioning for a partition location is computed, + * by putting primitives whose centroid is on the left and right of the split + * location to different sets. The SAH is evaluated by computing the number of + * blocks occupied by the primitives in the partitions. */ + +class BVHObjectBinning : public BVHRange +{ +public: + __forceinline BVHObjectBinning() {} + BVHObjectBinning(const BVHRange& job, BVHReference *prims); + + void split(BVHReference *prims, BVHObjectBinning& left_o, BVHObjectBinning& right_o) const; + + float splitSAH; /* SAH cost of the best split */ + float leafSAH; /* SAH cost of creating a leaf */ + +protected: + int dim; /* best split dimension */ + int pos; /* best split position */ + size_t num_bins; /* actual number of bins to use */ + float3 scale; /* scaling factor to compute bin */ + + enum { MAX_BINS = 32 }; + enum { LOG_BLOCK_SIZE = 2 }; + + /* computes the bin numbers for each dimension for a box. */ + __forceinline int4 get_bin(const BoundBox& box) const + { + int4 a = make_int4((box.center2() - cent_bounds().min)*scale - make_float3(0.5f)); + int4 mn = make_int4(0); + int4 mx = make_int4((int)num_bins-1); + + return clamp(a, mn, mx); + } + + /* computes the bin numbers for each dimension for a point. */ + __forceinline int4 get_bin(const float3& c) const + { + return make_int4((c - cent_bounds().min)*scale - make_float3(0.5f)); + } + + /* compute the number of blocks occupied for each dimension. */ + __forceinline float4 blocks(const int4& a) const + { + return make_float4((a + make_int4((1 << LOG_BLOCK_SIZE)-1)) >> LOG_BLOCK_SIZE); + } + + /* compute the number of blocks occupied in one dimension. */ + __forceinline int blocks(size_t a) const + { + return (int)((a+((1LL << LOG_BLOCK_SIZE)-1)) >> LOG_BLOCK_SIZE); + } +}; + +CCL_NAMESPACE_END + +#endif + diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 38674c2c561..c5b4f1d01ae 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -15,22 +15,36 @@ * limitations under the License. */ +#include "bvh_binning.h" #include "bvh_build.h" #include "bvh_node.h" #include "bvh_params.h" -#include "bvh_sort.h" +#include "bvh_split.h" #include "mesh.h" #include "object.h" #include "scene.h" -#include "util_algorithm.h" +#include "util_debug.h" #include "util_foreach.h" #include "util_progress.h" #include "util_time.h" CCL_NAMESPACE_BEGIN +/* BVH Build Task */ + +class BVHBuildTask : public Task { +public: + BVHBuildTask(InnerNode *node_, int child_, BVHObjectBinning& range_, int level_) + : node(node_), child(child_), level(level_), range(range_) {} + + InnerNode *node; + int child; + int level; + BVHObjectBinning range; +}; + /* Constructor / Destructor */ BVHBuild::BVHBuild(const vector& objects_, @@ -41,10 +55,10 @@ BVHBuild::BVHBuild(const vector& objects_, prim_object(prim_object_), params(params_), progress(progress_), - progress_start_time(0.0) + progress_start_time(0.0), + task_pool(function_bind(&BVHBuild::thread_build_node, this, _1, _2)) { spatial_min_overlap = 0.0f; - progress_num_duplicates = 0; } BVHBuild::~BVHBuild() @@ -53,57 +67,63 @@ BVHBuild::~BVHBuild() /* Adding References */ -void BVHBuild::add_reference_mesh(NodeSpec& root, Mesh *mesh, int i) +void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i) { for(uint j = 0; j < mesh->triangles.size(); j++) { Mesh::Triangle t = mesh->triangles[j]; - Reference ref; + BoundBox bounds = BoundBox::empty; for(int k = 0; k < 3; k++) { float3 pt = mesh->verts[t.v[k]]; - ref.bounds.grow(pt); + bounds.grow(pt); } - if(ref.bounds.valid()) { - ref.prim_index = j; - ref.prim_object = i; - - references.push_back(ref); - root.bounds.grow(ref.bounds); + if(bounds.valid()) { + references.push_back(BVHReference(bounds, j, i)); + root.grow(bounds); + center.grow(bounds.center2()); } } } -void BVHBuild::add_reference_object(NodeSpec& root, Object *ob, int i) +void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i) { - Reference ref; - - ref.prim_index = -1; - ref.prim_object = i; - ref.bounds = ob->bounds; - - references.push_back(ref); - root.bounds.grow(ref.bounds); + references.push_back(BVHReference(ob->bounds, -1, i)); + root.grow(ob->bounds); + center.grow(ob->bounds.center2()); } -void BVHBuild::add_references(NodeSpec& root) +void BVHBuild::add_references(BVHRange& root) { - /* init root spec */ - root.num = 0; - root.bounds = BoundBox(); + /* reserve space for references */ + size_t num_alloc_references = 0; - /* add objects */ + foreach(Object *ob, objects) { + if(params.top_level) { + if(ob->mesh->transform_applied) + num_alloc_references += ob->mesh->triangles.size(); + else + num_alloc_references++; + } + else + num_alloc_references += ob->mesh->triangles.size(); + } + + references.reserve(num_alloc_references); + + /* add references from objects */ + BoundBox bounds = BoundBox::empty, center = BoundBox::empty; int i = 0; foreach(Object *ob, objects) { if(params.top_level) { if(ob->mesh->transform_applied) - add_reference_mesh(root, ob->mesh, i); + add_reference_mesh(bounds, center, ob->mesh, i); else - add_reference_object(root, ob, i); + add_reference_object(bounds, center, ob, i); } else - add_reference_mesh(root, ob->mesh, i); + add_reference_mesh(bounds, center, ob->mesh, i); i++; @@ -111,129 +131,213 @@ void BVHBuild::add_references(NodeSpec& root) } /* happens mostly on empty meshes */ - if(!root.bounds.valid()) - root.bounds.grow(make_float3(0.0f, 0.0f, 0.0f)); + if(!bounds.valid()) + bounds.grow(make_float3(0.0f, 0.0f, 0.0f)); - root.num = references.size(); + root = BVHRange(bounds, center, 0, references.size()); } /* Build */ BVHNode* BVHBuild::run() { - NodeSpec root; + BVHRange root; /* add references */ add_references(root); - if(progress.get_cancel()) return NULL; + if(progress.get_cancel()) + return NULL; /* init spatial splits */ if(params.top_level) /* todo: get rid of this */ params.use_spatial_split = false; - spatial_min_overlap = root.bounds.area() * params.spatial_split_alpha; + spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha; spatial_right_bounds.clear(); - spatial_right_bounds.resize(max(root.num, (int)BVHParams::NUM_SPATIAL_BINS) - 1); + spatial_right_bounds.resize(max(root.size(), (int)BVHParams::NUM_SPATIAL_BINS) - 1); /* init progress updates */ - progress_num_duplicates = 0; progress_start_time = time_dt(); + progress_count = 0; + progress_total = references.size(); + progress_original_total = progress_total; + + prim_index.resize(references.size()); + prim_object.resize(references.size()); /* build recursively */ - return build_node(root, 0, 0.0f, 1.0f); + BVHNode *rootnode; + + if(params.use_spatial_split) { + /* singlethreaded spatial split build */ + rootnode = build_node(root, 0); + } + else { + /* multithreaded binning build */ + BVHObjectBinning rootbin(root, &references[0]); + rootnode = build_node(rootbin, 0); + task_pool.wait(); + } + + /* delete if we cancelled */ + if(rootnode) { + if(progress.get_cancel()) { + rootnode->deleteSubtree(); + rootnode = NULL; + } + else if(!params.use_spatial_split) { + /*rotate(rootnode, 4, 5);*/ + rootnode->update_visibility(); + } + } + + return rootnode; } -void BVHBuild::progress_update(float progress_start, float progress_end) +void BVHBuild::progress_update() { if(time_dt() - progress_start_time < 0.25f) return; + + double progress_start = (double)progress_count/(double)progress_total; + double duplicates = (double)(progress_total - progress_original_total)/(double)progress_total; - float duplicates = (float)progress_num_duplicates/(float)references.size(); string msg = string_printf("Building BVH %.0f%%, duplicates %.0f%%", progress_start*100.0f, duplicates*100.0f); progress.set_substatus(msg); - progress_start_time = time_dt(); + progress_start_time = time_dt(); } -BVHNode* BVHBuild::build_node(const NodeSpec& spec, int level, float progress_start, float progress_end) +void BVHBuild::thread_build_node(Task *task_, int thread_id) { - /* progress update */ - progress_update(progress_start, progress_end); - if(progress.get_cancel()) return NULL; + if(progress.get_cancel()) + return; - /* small enough or too deep => create leaf. */ - if(spec.num <= params.min_leaf_size || level >= BVHParams::MAX_DEPTH) - return create_leaf_node(spec); + /* build nodes */ + BVHBuildTask *task = (BVHBuildTask*)task_; + BVHNode *node = build_node(task->range, task->level); - /* find split candidates. */ - float area = spec.bounds.area(); - float leafSAH = area * params.triangle_cost(spec.num); - float nodeSAH = area * params.node_cost(2); - ObjectSplit object = find_object_split(spec, nodeSAH); - SpatialSplit spatial; + /* set child in inner node */ + task->node->children[task->child] = node; - if(params.use_spatial_split && level < BVHParams::MAX_SPATIAL_DEPTH) { - BoundBox overlap = object.left_bounds; - overlap.intersect(object.right_bounds); + /* update progress */ + if(task->range.size() < THREAD_TASK_SIZE) { + /*rotate(node, INT_MAX, 5);*/ - if(overlap.area() >= spatial_min_overlap) - spatial = find_spatial_split(spec, nodeSAH); + thread_scoped_lock lock(build_mutex); + + progress_count += task->range.size(); + progress_update(); } +} - /* leaf SAH is the lowest => create leaf. */ - float minSAH = min(min(leafSAH, object.sah), spatial.sah); +/* multithreaded binning builder */ +BVHNode* BVHBuild::build_node(const BVHObjectBinning& range, int level) +{ + size_t size = range.size(); + float leafSAH = params.sah_triangle_cost * range.leafSAH; + float splitSAH = params.sah_node_cost * range.bounds().half_area() + params.sah_triangle_cost * range.splitSAH; - if(minSAH == leafSAH && spec.num <= params.max_leaf_size) - return create_leaf_node(spec); + /* make leaf node when threshold reached or SAH tells us */ + if(params.small_enough_for_leaf(size, level) || (size <= params.max_leaf_size && leafSAH < splitSAH)) + return create_leaf_node(range); - /* perform split. */ - NodeSpec left, right; - - if(params.use_spatial_split && minSAH == spatial.sah) - do_spatial_split(left, right, spec, spatial); - if(!left.num || !right.num) - do_object_split(left, right, spec, object); + /* perform split */ + BVHObjectBinning left, right; + range.split(&references[0], left, right); /* create inner node. */ - progress_num_duplicates += left.num + right.num - spec.num; + InnerNode *inner; - float progress_mid = lerp(progress_start, progress_end, (float)right.num / (float)(left.num + right.num)); + if(range.size() < THREAD_TASK_SIZE) { + /* local build */ + BVHNode *leftnode = build_node(left, level + 1); + BVHNode *rightnode = build_node(right, level + 1); - BVHNode* rightNode = build_node(right, level + 1, progress_start, progress_mid); - if(progress.get_cancel()) { - if(rightNode) rightNode->deleteSubtree(); - return NULL; + inner = new InnerNode(range.bounds(), leftnode, rightnode); + } + else { + /* threaded build */ + inner = new InnerNode(range.bounds()); + + task_pool.push(new BVHBuildTask(inner, 0, left, level + 1), true); + task_pool.push(new BVHBuildTask(inner, 1, right, level + 1), true); } - BVHNode* leftNode = build_node(left, level + 1, progress_mid, progress_end); - if(progress.get_cancel()) { - if(leftNode) leftNode->deleteSubtree(); - return NULL; - } - - return new InnerNode(spec.bounds, leftNode, rightNode); + return inner; } -BVHNode *BVHBuild::create_object_leaf_nodes(const Reference *ref, int num) +/* single threaded spatial split builder */ +BVHNode* BVHBuild::build_node(const BVHRange& range, int level) +{ + /* progress update */ + progress_update(); + if(progress.get_cancel()) + return NULL; + + /* small enough or too deep => create leaf. */ + if(params.small_enough_for_leaf(range.size(), level)) { + progress_count += range.size(); + return create_leaf_node(range); + } + + /* splitting test */ + BVHMixedSplit split(this, range, level); + + if(split.no_split) { + progress_count += range.size(); + return create_leaf_node(range); + } + + /* do split */ + BVHRange left, right; + split.split(this, left, right, range); + + progress_total += left.size() + right.size() - range.size(); + size_t total = progress_total; + + /* leaft node */ + BVHNode *leftnode = build_node(left, level + 1); + + /* right node (modify start for splits) */ + right.set_start(right.start() + progress_total - total); + BVHNode *rightnode = build_node(right, level + 1); + + /* inner node */ + return new InnerNode(range.bounds(), leftnode, rightnode); +} + +/* Create Nodes */ + +BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, int num) { if(num == 0) { - BoundBox bounds; + BoundBox bounds = BoundBox::empty; return new LeafNode(bounds, 0, 0, 0); } else if(num == 1) { - prim_index.push_back(ref[0].prim_index); - prim_object.push_back(ref[0].prim_object); - uint visibility = objects[ref[0].prim_object]->visibility; - return new LeafNode(ref[0].bounds, visibility, prim_index.size()-1, prim_index.size()); + if(start == prim_index.size()) { + assert(params.use_spatial_split); + + prim_index.push_back(ref->prim_index()); + prim_object.push_back(ref->prim_object()); + } + else { + prim_index[start] = ref->prim_index(); + prim_object[start] = ref->prim_object(); + } + + uint visibility = objects[ref->prim_object()]->visibility; + return new LeafNode(ref->bounds(), visibility, start, start+1); } else { int mid = num/2; - BVHNode *leaf0 = create_object_leaf_nodes(ref, mid); - BVHNode *leaf1 = create_object_leaf_nodes(ref+mid, num-mid); + BVHNode *leaf0 = create_object_leaf_nodes(ref, start, mid); + BVHNode *leaf1 = create_object_leaf_nodes(ref+mid, start+mid, num-mid); - BoundBox bounds; + BoundBox bounds = BoundBox::empty; bounds.grow(leaf0->m_bounds); bounds.grow(leaf1->m_bounds); @@ -241,310 +345,136 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const Reference *ref, int num) } } -BVHNode* BVHBuild::create_leaf_node(const NodeSpec& spec) +BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) { vector& p_index = prim_index; vector& p_object = prim_object; - BoundBox bounds; - int num = 0; + BoundBox bounds = BoundBox::empty; + int num = 0, ob_num = 0; uint visibility = 0; - for(int i = 0; i < spec.num; i++) { - if(references.back().prim_index != -1) { - p_index.push_back(references.back().prim_index); - p_object.push_back(references.back().prim_object); - bounds.grow(references.back().bounds); - visibility |= objects[references.back().prim_object]->visibility; - references.pop_back(); + for(int i = 0; i < range.size(); i++) { + BVHReference& ref = references[range.start() + i]; + + if(ref.prim_index() != -1) { + if(range.start() + num == prim_index.size()) { + assert(params.use_spatial_split); + + p_index.push_back(ref.prim_index()); + p_object.push_back(ref.prim_object()); + } + else { + p_index[range.start() + num] = ref.prim_index(); + p_object[range.start() + num] = ref.prim_object(); + } + + bounds.grow(ref.bounds()); + visibility |= objects[ref.prim_object()]->visibility; num++; } + else { + if(ob_num < i) + references[range.start() + ob_num] = ref; + ob_num++; + } } BVHNode *leaf = NULL; if(num > 0) { - leaf = new LeafNode(bounds, visibility, p_index.size() - num, p_index.size()); + leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num); - if(num == spec.num) + if(num == range.size()) return leaf; } /* while there may be multiple triangles in a leaf, for object primitives - * we want them to be the only one, so we */ - int ob_num = spec.num - num; - const Reference *ref = (ob_num)? &references.back() - (ob_num - 1): NULL; - BVHNode *oleaf = create_object_leaf_nodes(ref, ob_num); - for(int i = 0; i < ob_num; i++) - references.pop_back(); + * we want there to be the only one, so we keep splitting */ + const BVHReference *ref = (ob_num)? &references[range.start()]: NULL; + BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num); if(leaf) - return new InnerNode(spec.bounds, leaf, oleaf); + return new InnerNode(range.bounds(), leaf, oleaf); else return oleaf; } -/* Object Split */ +/* Tree Rotations */ -BVHBuild::ObjectSplit BVHBuild::find_object_split(const NodeSpec& spec, float nodeSAH) +void BVHBuild::rotate(BVHNode *node, int max_depth, int iterations) { - ObjectSplit split; - const Reference *ref_ptr = &references[references.size() - spec.num]; + /* in tested scenes, this resulted in slightly slower raytracing, so disabled + * it for now. could be implementation bug, or depend on the scene */ + if(node) + for(int i = 0; i < iterations; i++) + rotate(node, max_depth); +} - for(int dim = 0; dim < 3; dim++) { - /* sort references */ - bvh_reference_sort(references.size() - spec.num, references.size(), &references[0], dim); +void BVHBuild::rotate(BVHNode *node, int max_depth) +{ + /* nothing to rotate if we reached a leaf node. */ + if(node->is_leaf() || max_depth < 0) + return; + + InnerNode *parent = (InnerNode*)node; - /* sweep right to left and determine bounds. */ - BoundBox right_bounds; + /* rotate all children first */ + for(size_t c = 0; c < 2; c++) + rotate(parent->children[c], max_depth-1); - for(int i = spec.num - 1; i > 0; i--) { - right_bounds.grow(ref_ptr[i].bounds); - spatial_right_bounds[i - 1] = right_bounds; - } + /* compute current area of all children */ + BoundBox bounds0 = parent->children[0]->m_bounds; + BoundBox bounds1 = parent->children[1]->m_bounds; - /* sweep left to right and select lowest SAH. */ - BoundBox left_bounds; + float area0 = bounds0.half_area(); + float area1 = bounds1.half_area(); + float4 child_area = make_float4(area0, area1, 0.0f, 0.0f); - for(int i = 1; i < spec.num; i++) { - left_bounds.grow(ref_ptr[i - 1].bounds); - right_bounds = spatial_right_bounds[i - 1]; + /* find best rotation. we pick a target child of a first child, and swap + * this with an other child. we perform the best such swap. */ + float best_cost = FLT_MAX; + int best_child = -1, bets_target = -1, best_other = -1; - float sah = nodeSAH + - left_bounds.area() * params.triangle_cost(i) + - right_bounds.area() * params.triangle_cost(spec.num - i); + for(size_t c = 0; c < 2; c++) { + /* ignore leaf nodes as we cannot descent into */ + if(parent->children[c]->is_leaf()) + continue; - if(sah < split.sah) { - split.sah = sah; - split.dim = dim; - split.num_left = i; - split.left_bounds = left_bounds; - split.right_bounds = right_bounds; + InnerNode *child = (InnerNode*)parent->children[c]; + BoundBox& other = (c == 0)? bounds1: bounds0; + + /* transpose child bounds */ + BoundBox target0 = child->children[0]->m_bounds; + BoundBox target1 = child->children[1]->m_bounds; + + /* compute cost for both possible swaps */ + float cost0 = merge(other, target1).half_area() - child_area[c]; + float cost1 = merge(target0, other).half_area() - child_area[c]; + + if(min(cost0,cost1) < best_cost) { + best_child = (int)c; + best_other = (int)(1-c); + + if(cost0 < cost1) { + best_cost = cost0; + bets_target = 0; + } + else { + best_cost = cost0; + bets_target = 1; } } } - return split; -} + /* if we did not find a swap that improves the SAH then do nothing */ + if(best_cost >= 0) + return; -void BVHBuild::do_object_split(NodeSpec& left, NodeSpec& right, const NodeSpec& spec, const ObjectSplit& split) -{ - /* sort references according to split */ - int start = references.size() - spec.num; - int end = references.size(); /* todo: is this right? */ + /* perform the best found tree rotation */ + InnerNode *child = (InnerNode*)parent->children[best_child]; - bvh_reference_sort(start, end, &references[0], split.dim); - - /* split node specs */ - left.num = split.num_left; - left.bounds = split.left_bounds; - right.num = spec.num - split.num_left; - right.bounds = split.right_bounds; -} - -/* Spatial Split */ - -BVHBuild::SpatialSplit BVHBuild::find_spatial_split(const NodeSpec& spec, float nodeSAH) -{ - /* initialize bins. */ - float3 origin = spec.bounds.min; - float3 binSize = (spec.bounds.max - origin) * (1.0f / (float)BVHParams::NUM_SPATIAL_BINS); - float3 invBinSize = 1.0f / binSize; - - for(int dim = 0; dim < 3; dim++) { - for(int i = 0; i < BVHParams::NUM_SPATIAL_BINS; i++) { - SpatialBin& bin = spatial_bins[dim][i]; - - bin.bounds = BoundBox(); - bin.enter = 0; - bin.exit = 0; - } - } - - /* chop references into bins. */ - for(unsigned int refIdx = references.size() - spec.num; refIdx < references.size(); refIdx++) { - const Reference& ref = references[refIdx]; - float3 firstBinf = (ref.bounds.min - origin) * invBinSize; - float3 lastBinf = (ref.bounds.max - origin) * invBinSize; - int3 firstBin = make_int3((int)firstBinf.x, (int)firstBinf.y, (int)firstBinf.z); - int3 lastBin = make_int3((int)lastBinf.x, (int)lastBinf.y, (int)lastBinf.z); - - firstBin = clamp(firstBin, 0, BVHParams::NUM_SPATIAL_BINS - 1); - lastBin = clamp(lastBin, firstBin, BVHParams::NUM_SPATIAL_BINS - 1); - - for(int dim = 0; dim < 3; dim++) { - Reference currRef = ref; - - for(int i = firstBin[dim]; i < lastBin[dim]; i++) { - Reference leftRef, rightRef; - - split_reference(leftRef, rightRef, currRef, dim, origin[dim] + binSize[dim] * (float)(i + 1)); - spatial_bins[dim][i].bounds.grow(leftRef.bounds); - currRef = rightRef; - } - - spatial_bins[dim][lastBin[dim]].bounds.grow(currRef.bounds); - spatial_bins[dim][firstBin[dim]].enter++; - spatial_bins[dim][lastBin[dim]].exit++; - } - } - - /* select best split plane. */ - SpatialSplit split; - - for(int dim = 0; dim < 3; dim++) { - /* sweep right to left and determine bounds. */ - BoundBox right_bounds; - - for(int i = BVHParams::NUM_SPATIAL_BINS - 1; i > 0; i--) { - right_bounds.grow(spatial_bins[dim][i].bounds); - spatial_right_bounds[i - 1] = right_bounds; - } - - /* sweep left to right and select lowest SAH. */ - BoundBox left_bounds; - int leftNum = 0; - int rightNum = spec.num; - - for(int i = 1; i < BVHParams::NUM_SPATIAL_BINS; i++) { - left_bounds.grow(spatial_bins[dim][i - 1].bounds); - leftNum += spatial_bins[dim][i - 1].enter; - rightNum -= spatial_bins[dim][i - 1].exit; - - float sah = nodeSAH + - left_bounds.area() * params.triangle_cost(leftNum) + - spatial_right_bounds[i - 1].area() * params.triangle_cost(rightNum); - - if(sah < split.sah) { - split.sah = sah; - split.dim = dim; - split.pos = origin[dim] + binSize[dim] * (float)i; - } - } - } - - return split; -} - -void BVHBuild::do_spatial_split(NodeSpec& left, NodeSpec& right, const NodeSpec& spec, const SpatialSplit& split) -{ - /* Categorize references and compute bounds. - * - * Left-hand side: [left_start, left_end[ - * Uncategorized/split: [left_end, right_start[ - * Right-hand side: [right_start, refs.size()[ */ - - vector& refs = references; - int left_start = refs.size() - spec.num; - int left_end = left_start; - int right_start = refs.size(); - - left.bounds = right.bounds = BoundBox(); - - for(int i = left_end; i < right_start; i++) { - if(refs[i].bounds.max[split.dim] <= split.pos) { - /* entirely on the left-hand side */ - left.bounds.grow(refs[i].bounds); - swap(refs[i], refs[left_end++]); - } - else if(refs[i].bounds.min[split.dim] >= split.pos) { - /* entirely on the right-hand side */ - right.bounds.grow(refs[i].bounds); - swap(refs[i--], refs[--right_start]); - } - } - - /* duplicate or unsplit references intersecting both sides. */ - while(left_end < right_start) { - /* split reference. */ - Reference lref, rref; - - split_reference(lref, rref, refs[left_end], split.dim, split.pos); - - /* compute SAH for duplicate/unsplit candidates. */ - BoundBox lub = left.bounds; // Unsplit to left: new left-hand bounds. - BoundBox rub = right.bounds; // Unsplit to right: new right-hand bounds. - BoundBox ldb = left.bounds; // Duplicate: new left-hand bounds. - BoundBox rdb = right.bounds; // Duplicate: new right-hand bounds. - - lub.grow(refs[left_end].bounds); - rub.grow(refs[left_end].bounds); - ldb.grow(lref.bounds); - rdb.grow(rref.bounds); - - float lac = params.triangle_cost(left_end - left_start); - float rac = params.triangle_cost(refs.size() - right_start); - float lbc = params.triangle_cost(left_end - left_start + 1); - float rbc = params.triangle_cost(refs.size() - right_start + 1); - - float unsplitLeftSAH = lub.area() * lbc + right.bounds.area() * rac; - float unsplitRightSAH = left.bounds.area() * lac + rub.area() * rbc; - float duplicateSAH = ldb.area() * lbc + rdb.area() * rbc; - float minSAH = min(min(unsplitLeftSAH, unsplitRightSAH), duplicateSAH); - - if(minSAH == unsplitLeftSAH) { - /* unsplit to left */ - left.bounds = lub; - left_end++; - } - else if(minSAH == unsplitRightSAH) { - /* unsplit to right */ - right.bounds = rub; - swap(refs[left_end], refs[--right_start]); - } - else { - /* duplicate */ - left.bounds = ldb; - right.bounds = rdb; - refs[left_end++] = lref; - refs.push_back(rref); - } - } - - left.num = left_end - left_start; - right.num = refs.size() - right_start; -} - -void BVHBuild::split_reference(Reference& left, Reference& right, const Reference& ref, int dim, float pos) -{ - /* initialize references. */ - left.prim_index = right.prim_index = ref.prim_index; - left.prim_object = right.prim_object = ref.prim_object; - left.bounds = right.bounds = BoundBox(); - - /* loop over vertices/edges. */ - Object *ob = objects[ref.prim_object]; - const Mesh *mesh = ob->mesh; - const int *inds = mesh->triangles[ref.prim_index].v; - const float3 *verts = &mesh->verts[0]; - const float3* v1 = &verts[inds[2]]; - - for(int i = 0; i < 3; i++) { - const float3* v0 = v1; - int vindex = inds[i]; - v1 = &verts[vindex]; - float v0p = (*v0)[dim]; - float v1p = (*v1)[dim]; - - /* insert vertex to the boxes it belongs to. */ - if(v0p <= pos) - left.bounds.grow(*v0); - - if(v0p >= pos) - right.bounds.grow(*v0); - - /* edge intersects the plane => insert intersection to both boxes. */ - if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { - float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); - left.bounds.grow(t); - right.bounds.grow(t); - } - } - - /* intersect with original bounds. */ - left.bounds.max[dim] = pos; - right.bounds.min[dim] = pos; - left.bounds.intersect(ref.bounds); - right.bounds.intersect(ref.bounds); + swap(parent->children[best_other], child->children[bets_target]); + child->m_bounds = merge(child->children[0]->m_bounds, child->children[1]->m_bounds); } CCL_NAMESPACE_END diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h index 1fa1951d7f2..84e14632b4b 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -21,8 +21,10 @@ #include #include "bvh.h" +#include "bvh_binning.h" #include "util_boundbox.h" +#include "util_task.h" #include "util_vector.h" CCL_NAMESPACE_BEGIN @@ -37,28 +39,7 @@ class Progress; class BVHBuild { public: - struct Reference - { - int prim_index; - int prim_object; - BoundBox bounds; - - Reference() - { - } - }; - - struct NodeSpec - { - int num; - BoundBox bounds; - - NodeSpec() - { - num = 0; - } - }; - + /* Constructor/Destructor */ BVHBuild( const vector& objects, vector& prim_index, @@ -70,63 +51,37 @@ public: BVHNode *run(); protected: + friend class BVHMixedSplit; + friend class BVHObjectSplit; + friend class BVHSpatialSplit; + /* adding references */ - void add_reference_mesh(NodeSpec& root, Mesh *mesh, int i); - void add_reference_object(NodeSpec& root, Object *ob, int i); - void add_references(NodeSpec& root); + void add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i); + void add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i); + void add_references(BVHRange& root); /* building */ - BVHNode *build_node(const NodeSpec& spec, int level, float progress_start, float progress_end); - BVHNode *create_leaf_node(const NodeSpec& spec); - BVHNode *create_object_leaf_nodes(const Reference *ref, int num); + BVHNode *build_node(const BVHRange& range, int level); + BVHNode *build_node(const BVHObjectBinning& range, int level); + BVHNode *create_leaf_node(const BVHRange& range); + BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num); - void progress_update(float progress_start, float progress_end); + /* threads */ + enum { THREAD_TASK_SIZE = 4096 }; + void thread_build_node(Task *task_, int thread_id); + thread_mutex build_mutex; - /* object splits */ - struct ObjectSplit - { - float sah; - int dim; - int num_left; - BoundBox left_bounds; - BoundBox right_bounds; + /* progress */ + void progress_update(); - ObjectSplit() - : sah(FLT_MAX), dim(0), num_left(0) - { - } - }; - - ObjectSplit find_object_split(const NodeSpec& spec, float nodeSAH); - void do_object_split(NodeSpec& left, NodeSpec& right, const NodeSpec& spec, const ObjectSplit& split); - - /* spatial splits */ - struct SpatialSplit - { - float sah; - int dim; - float pos; - - SpatialSplit() - : sah(FLT_MAX), dim(0), pos(0.0f) - { - } - }; - - struct SpatialBin - { - BoundBox bounds; - int enter; - int exit; - }; - - SpatialSplit find_spatial_split(const NodeSpec& spec, float nodeSAH); - void do_spatial_split(NodeSpec& left, NodeSpec& right, const NodeSpec& spec, const SpatialSplit& split); - void split_reference(Reference& left, Reference& right, const Reference& ref, int dim, float pos); + /* tree rotations */ + void rotate(BVHNode *node, int max_depth); + void rotate(BVHNode *node, int max_depth, int iterations); /* objects and primitive references */ vector objects; - vector references; + vector references; + int num_original_references; /* output primitive indexes and objects */ vector& prim_index; @@ -138,12 +93,17 @@ protected: /* progress reporting */ Progress& progress; double progress_start_time; - int progress_num_duplicates; + size_t progress_count; + size_t progress_total; + size_t progress_original_total; /* spatial splitting */ float spatial_min_overlap; vector spatial_right_bounds; - SpatialBin spatial_bins[3][BVHParams::NUM_SPATIAL_BINS]; + BVHSpatialBin spatial_bins[3][BVHParams::NUM_SPATIAL_BINS]; + + /* threads */ + TaskPool task_pool; }; CCL_NAMESPACE_END diff --git a/intern/cycles/bvh/bvh_node.cpp b/intern/cycles/bvh/bvh_node.cpp index 63683bae4a3..4edfb4b70a4 100644 --- a/intern/cycles/bvh/bvh_node.cpp +++ b/intern/cycles/bvh/bvh_node.cpp @@ -24,6 +24,8 @@ CCL_NAMESPACE_BEGIN +/* BVH Node */ + int BVHNode::getSubtreeSize(BVH_STAT stat) const { int cnt = 0; @@ -59,7 +61,8 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const void BVHNode::deleteSubtree() { for(int i=0;ideleteSubtree(); + if(get_child(i)) + get_child(i)->deleteSubtree(); delete this; } @@ -70,12 +73,27 @@ float BVHNode::computeSubtreeSAHCost(const BVHParams& p, float probability) cons for(int i=0;icomputeSubtreeSAHCost(p, probability * child->m_bounds.area()/m_bounds.area()); + SAH += child->computeSubtreeSAHCost(p, probability * child->m_bounds.safe_area()/m_bounds.safe_area()); } return SAH; } +uint BVHNode::update_visibility() +{ + if(!is_leaf() && m_visibility == 0) { + InnerNode *inner = (InnerNode*)this; + BVHNode *child0 = inner->children[0]; + BVHNode *child1 = inner->children[1]; + + m_visibility = child0->update_visibility()|child1->update_visibility(); + } + + return m_visibility; +} + +/* Inner Node */ + void InnerNode::print(int depth) const { for(int i = 0; i < depth; i++) diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h index 5e0a17a1193..5c00f7b7a38 100644 --- a/intern/cycles/bvh/bvh_node.h +++ b/intern/cycles/bvh/bvh_node.h @@ -49,8 +49,6 @@ public: virtual int num_triangles() const { return 0; } virtual void print(int depth = 0) const = 0; - float getArea() const { return m_bounds.area(); } - BoundBox m_bounds; uint m_visibility; @@ -58,6 +56,8 @@ public: int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const; float computeSubtreeSAHCost(const BVHParams& p, float probability = 1.0f) const; void deleteSubtree(); + + uint update_visibility(); }; class InnerNode : public BVHNode @@ -66,9 +66,21 @@ public: InnerNode(const BoundBox& bounds, BVHNode* child0, BVHNode* child1) { m_bounds = bounds; - m_visibility = child0->m_visibility|child1->m_visibility; children[0] = child0; children[1] = child1; + + if(child0 && child1) + m_visibility = child0->m_visibility|child1->m_visibility; + else + m_visibility = 0; /* happens on build cancel */ + } + + InnerNode(const BoundBox& bounds) + { + m_bounds = bounds; + m_visibility = 0; + children[0] = NULL; + children[1] = NULL; } bool is_leaf() const { return false; } diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index 38093438500..0cf5e905fea 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -18,6 +18,8 @@ #ifndef __BVH_PARAMS_H__ #define __BVH_PARAMS_H__ +#include "util_boundbox.h" + CCL_NAMESPACE_BEGIN /* BVH Parameters */ @@ -73,14 +75,97 @@ public: } /* SAH costs */ - float cost(int num_nodes, int num_tris) const + __forceinline float cost(int num_nodes, int num_tris) const { return node_cost(num_nodes) + triangle_cost(num_tris); } - float triangle_cost(int n) const + __forceinline float triangle_cost(int n) const { return n*sah_triangle_cost; } - float node_cost(int n) const + __forceinline float node_cost(int n) const { return n*sah_node_cost; } + + __forceinline bool small_enough_for_leaf(int size, int level) + { return (size <= min_leaf_size || level >= MAX_DEPTH); } +}; + +/* BVH Reference + * + * Reference to a primitive. Primitive index and object are sneakily packed + * into BoundBox to reduce memory usage and align nicely */ + +class BVHReference +{ +public: + __forceinline BVHReference() {} + + __forceinline BVHReference(const BoundBox& bounds_, int prim_index, int prim_object) + : rbounds(bounds_) + { + rbounds.min.w = __int_as_float(prim_index); + rbounds.max.w = __int_as_float(prim_object); + } + + __forceinline const BoundBox& bounds() const { return rbounds; } + __forceinline int prim_index() const { return __float_as_int(rbounds.min.w); } + __forceinline int prim_object() const { return __float_as_int(rbounds.max.w); } + +protected: + BoundBox rbounds; +}; + +/* BVH Range + * + * Build range used during construction, to indicate the bounds and place in + * the reference array of a subset of pirmitives Again uses trickery to pack + * integers into BoundBox for alignment purposes. */ + +class BVHRange +{ +public: + __forceinline BVHRange() + { + rbounds.min.w = __int_as_float(0); + rbounds.max.w = __int_as_float(0); + } + + __forceinline BVHRange(const BoundBox& bounds_, int start_, int size_) + : rbounds(bounds_) + { + rbounds.min.w = __int_as_float(start_); + rbounds.max.w = __int_as_float(size_); + } + + __forceinline BVHRange(const BoundBox& bounds_, const BoundBox& cbounds_, int start_, int size_) + : rbounds(bounds_), cbounds(cbounds_) + { + rbounds.min.w = __int_as_float(start_); + rbounds.max.w = __int_as_float(size_); + } + + __forceinline void set_start(int start_) { rbounds.min.w = __int_as_float(start_); } + + __forceinline const BoundBox& bounds() const { return rbounds; } + __forceinline const BoundBox& cent_bounds() const { return cbounds; } + __forceinline int start() const { return __float_as_int(rbounds.min.w); } + __forceinline int size() const { return __float_as_int(rbounds.max.w); } + __forceinline int end() const { return start() + size(); } + +protected: + BoundBox rbounds; + BoundBox cbounds; +}; + +/* BVH Spatial Bin */ + +struct BVHSpatialBin +{ + BoundBox bounds; + int enter; + int exit; + + __forceinline BVHSpatialBin() + { + } }; CCL_NAMESPACE_END diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp index ee4531a4843..bef384be592 100644 --- a/intern/cycles/bvh/bvh_sort.cpp +++ b/intern/cycles/bvh/bvh_sort.cpp @@ -32,23 +32,23 @@ public: dim = dim_; } - bool operator()(const BVHBuild::Reference& ra, const BVHBuild::Reference& rb) + bool operator()(const BVHReference& ra, const BVHReference& rb) { - float ca = ra.bounds.min[dim] + ra.bounds.max[dim]; - float cb = rb.bounds.min[dim] + rb.bounds.max[dim]; + float ca = ra.bounds().min[dim] + ra.bounds().max[dim]; + float cb = rb.bounds().min[dim] + rb.bounds().max[dim]; if(ca < cb) return true; else if(ca > cb) return false; - else if(ra.prim_object < rb.prim_object) return true; - else if(ra.prim_object > rb.prim_object) return false; - else if(ra.prim_index < rb.prim_index) return true; - else if(ra.prim_index > rb.prim_index) return false; + else if(ra.prim_object() < rb.prim_object()) return true; + else if(ra.prim_object() > rb.prim_object()) return false; + else if(ra.prim_index() < rb.prim_index()) return true; + else if(ra.prim_index() > rb.prim_index()) return false; return false; } }; -void bvh_reference_sort(int start, int end, BVHBuild::Reference *data, int dim) +void bvh_reference_sort(int start, int end, BVHReference *data, int dim) { sort(data+start, data+end, BVHReferenceCompare(dim)); } diff --git a/intern/cycles/bvh/bvh_sort.h b/intern/cycles/bvh/bvh_sort.h index f0676948146..ba35ba3fae7 100644 --- a/intern/cycles/bvh/bvh_sort.h +++ b/intern/cycles/bvh/bvh_sort.h @@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN -void bvh_reference_sort(int start, int end, BVHBuild::Reference *data, int dim); +void bvh_reference_sort(int start, int end, BVHReference *data, int dim); CCL_NAMESPACE_END diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp new file mode 100644 index 00000000000..263c5834428 --- /dev/null +++ b/intern/cycles/bvh/bvh_split.cpp @@ -0,0 +1,293 @@ +/* + * Adapted from code copyright 2009-2010 NVIDIA Corporation + * Modifications Copyright 2011, Blender Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bvh_build.h" +#include "bvh_split.h" +#include "bvh_sort.h" + +#include "mesh.h" +#include "object.h" + +#include "util_algorithm.h" + +CCL_NAMESPACE_BEGIN + +/* Object Split */ + +BVHObjectSplit::BVHObjectSplit(BVHBuild *builder, const BVHRange& range, float nodeSAH) +: sah(FLT_MAX), dim(0), num_left(0), left_bounds(BoundBox::empty), right_bounds(BoundBox::empty) +{ + const BVHReference *ref_ptr = &builder->references[range.start()]; + float min_sah = FLT_MAX; + + for(int dim = 0; dim < 3; dim++) { + /* sort references */ + bvh_reference_sort(range.start(), range.end(), &builder->references[0], dim); + + /* sweep right to left and determine bounds. */ + BoundBox right_bounds = BoundBox::empty; + + for(int i = range.size() - 1; i > 0; i--) { + right_bounds.grow(ref_ptr[i].bounds()); + builder->spatial_right_bounds[i - 1] = right_bounds; + } + + /* sweep left to right and select lowest SAH. */ + BoundBox left_bounds = BoundBox::empty; + + for(int i = 1; i < range.size(); i++) { + left_bounds.grow(ref_ptr[i - 1].bounds()); + right_bounds = builder->spatial_right_bounds[i - 1]; + + float sah = nodeSAH + + left_bounds.safe_area() * builder->params.triangle_cost(i) + + right_bounds.safe_area() * builder->params.triangle_cost(range.size() - i); + + if(sah < min_sah) { + min_sah = sah; + + this->sah = sah; + this->dim = dim; + this->num_left = i; + this->left_bounds = left_bounds; + this->right_bounds = right_bounds; + } + } + } +} + +void BVHObjectSplit::split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range) +{ + /* sort references according to split */ + bvh_reference_sort(range.start(), range.end(), &builder->references[0], this->dim); + + /* split node ranges */ + left = BVHRange(this->left_bounds, range.start(), this->num_left); + right = BVHRange(this->right_bounds, left.end(), range.size() - this->num_left); + +} + +/* Spatial Split */ + +BVHSpatialSplit::BVHSpatialSplit(BVHBuild *builder, const BVHRange& range, float nodeSAH) +: sah(FLT_MAX), dim(0), pos(0.0f) +{ + /* initialize bins. */ + float3 origin = range.bounds().min; + float3 binSize = (range.bounds().max - origin) * (1.0f / (float)BVHParams::NUM_SPATIAL_BINS); + float3 invBinSize = 1.0f / binSize; + + for(int dim = 0; dim < 3; dim++) { + for(int i = 0; i < BVHParams::NUM_SPATIAL_BINS; i++) { + BVHSpatialBin& bin = builder->spatial_bins[dim][i]; + + bin.bounds = BoundBox::empty; + bin.enter = 0; + bin.exit = 0; + } + } + + /* chop references into bins. */ + for(unsigned int refIdx = range.start(); refIdx < range.end(); refIdx++) { + const BVHReference& ref = builder->references[refIdx]; + float3 firstBinf = (ref.bounds().min - origin) * invBinSize; + float3 lastBinf = (ref.bounds().max - origin) * invBinSize; + int3 firstBin = make_int3((int)firstBinf.x, (int)firstBinf.y, (int)firstBinf.z); + int3 lastBin = make_int3((int)lastBinf.x, (int)lastBinf.y, (int)lastBinf.z); + + firstBin = clamp(firstBin, 0, BVHParams::NUM_SPATIAL_BINS - 1); + lastBin = clamp(lastBin, firstBin, BVHParams::NUM_SPATIAL_BINS - 1); + + for(int dim = 0; dim < 3; dim++) { + BVHReference currRef = ref; + + for(int i = firstBin[dim]; i < lastBin[dim]; i++) { + BVHReference leftRef, rightRef; + + split_reference(builder, leftRef, rightRef, currRef, dim, origin[dim] + binSize[dim] * (float)(i + 1)); + builder->spatial_bins[dim][i].bounds.grow(leftRef.bounds()); + currRef = rightRef; + } + + builder->spatial_bins[dim][lastBin[dim]].bounds.grow(currRef.bounds()); + builder->spatial_bins[dim][firstBin[dim]].enter++; + builder->spatial_bins[dim][lastBin[dim]].exit++; + } + } + + /* select best split plane. */ + for(int dim = 0; dim < 3; dim++) { + /* sweep right to left and determine bounds. */ + BoundBox right_bounds = BoundBox::empty; + + for(int i = BVHParams::NUM_SPATIAL_BINS - 1; i > 0; i--) { + right_bounds.grow(builder->spatial_bins[dim][i].bounds); + builder->spatial_right_bounds[i - 1] = right_bounds; + } + + /* sweep left to right and select lowest SAH. */ + BoundBox left_bounds = BoundBox::empty; + int leftNum = 0; + int rightNum = range.size(); + + for(int i = 1; i < BVHParams::NUM_SPATIAL_BINS; i++) { + left_bounds.grow(builder->spatial_bins[dim][i - 1].bounds); + leftNum += builder->spatial_bins[dim][i - 1].enter; + rightNum -= builder->spatial_bins[dim][i - 1].exit; + + float sah = nodeSAH + + left_bounds.safe_area() * builder->params.triangle_cost(leftNum) + + builder->spatial_right_bounds[i - 1].safe_area() * builder->params.triangle_cost(rightNum); + + if(sah < this->sah) { + this->sah = sah; + this->dim = dim; + this->pos = origin[dim] + binSize[dim] * (float)i; + } + } + } +} + +void BVHSpatialSplit::split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range) +{ + /* Categorize references and compute bounds. + * + * Left-hand side: [left_start, left_end[ + * Uncategorized/split: [left_end, right_start[ + * Right-hand side: [right_start, refs.size()[ */ + + vector& refs = builder->references; + int left_start = range.start(); + int left_end = left_start; + int right_start = range.end(); + int right_end = range.end(); + BoundBox left_bounds = BoundBox::empty; + BoundBox right_bounds = BoundBox::empty; + + for(int i = left_end; i < right_start; i++) { + if(refs[i].bounds().max[this->dim] <= this->pos) { + /* entirely on the left-hand side */ + left_bounds.grow(refs[i].bounds()); + swap(refs[i], refs[left_end++]); + } + else if(refs[i].bounds().min[this->dim] >= this->pos) { + /* entirely on the right-hand side */ + right_bounds.grow(refs[i].bounds()); + swap(refs[i--], refs[--right_start]); + } + } + + /* duplicate or unsplit references intersecting both sides. */ + while(left_end < right_start) { + /* split reference. */ + BVHReference lref, rref; + + split_reference(builder, lref, rref, refs[left_end], this->dim, this->pos); + + /* compute SAH for duplicate/unsplit candidates. */ + BoundBox lub = left_bounds; // Unsplit to left: new left-hand bounds. + BoundBox rub = right_bounds; // Unsplit to right: new right-hand bounds. + BoundBox ldb = left_bounds; // Duplicate: new left-hand bounds. + BoundBox rdb = right_bounds; // Duplicate: new right-hand bounds. + + lub.grow(refs[left_end].bounds()); + rub.grow(refs[left_end].bounds()); + ldb.grow(lref.bounds()); + rdb.grow(rref.bounds()); + + float lac = builder->params.triangle_cost(left_end - left_start); + float rac = builder->params.triangle_cost(right_end - right_start); + float lbc = builder->params.triangle_cost(left_end - left_start + 1); + float rbc = builder->params.triangle_cost(right_end - right_start + 1); + + float unsplitLeftSAH = lub.safe_area() * lbc + right_bounds.safe_area() * rac; + float unsplitRightSAH = left_bounds.safe_area() * lac + rub.safe_area() * rbc; + float duplicateSAH = ldb.safe_area() * lbc + rdb.safe_area() * rbc; + float minSAH = min(min(unsplitLeftSAH, unsplitRightSAH), duplicateSAH); + + if(minSAH == unsplitLeftSAH) { + /* unsplit to left */ + left_bounds = lub; + left_end++; + } + else if(minSAH == unsplitRightSAH) { + /* unsplit to right */ + right_bounds = rub; + swap(refs[left_end], refs[--right_start]); + } + else { + /* duplicate */ + left_bounds = ldb; + right_bounds = rdb; + refs[left_end++] = lref; + refs.insert(refs.begin() + right_end, rref); + right_end++; + } + } + + left = BVHRange(left_bounds, left_start, left_end - left_start); + right = BVHRange(right_bounds, right_start, right_end - right_start); +} + +void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVHReference& right, const BVHReference& ref, int dim, float pos) +{ + /* initialize boundboxes */ + BoundBox left_bounds = BoundBox::empty; + BoundBox right_bounds = BoundBox::empty; + + /* loop over vertices/edges. */ + Object *ob = builder->objects[ref.prim_object()]; + const Mesh *mesh = ob->mesh; + const int *inds = mesh->triangles[ref.prim_index()].v; + const float3 *verts = &mesh->verts[0]; + const float3* v1 = &verts[inds[2]]; + + for(int i = 0; i < 3; i++) { + const float3* v0 = v1; + int vindex = inds[i]; + v1 = &verts[vindex]; + float v0p = (*v0)[dim]; + float v1p = (*v1)[dim]; + + /* insert vertex to the boxes it belongs to. */ + if(v0p <= pos) + left_bounds.grow(*v0); + + if(v0p >= pos) + right_bounds.grow(*v0); + + /* edge intersects the plane => insert intersection to both boxes. */ + if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { + float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); + left_bounds.grow(t); + right_bounds.grow(t); + } + } + + /* intersect with original bounds. */ + left_bounds.max[dim] = pos; + right_bounds.min[dim] = pos; + left_bounds.intersect(ref.bounds()); + right_bounds.intersect(ref.bounds()); + + /* set referecnes */ + left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object()); + right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object()); +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/bvh/bvh_split.h b/intern/cycles/bvh/bvh_split.h new file mode 100644 index 00000000000..1f4befbe8e2 --- /dev/null +++ b/intern/cycles/bvh/bvh_split.h @@ -0,0 +1,110 @@ +/* + * Adapted from code copyright 2009-2010 NVIDIA Corporation + * Modifications Copyright 2011, Blender Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __BVH_SPLIT_H__ +#define __BVH_SPLIT_H__ + +#include "bvh_build.h" +#include "bvh_params.h" + +CCL_NAMESPACE_BEGIN + +class BVHBuild; + +/* Object Split */ + +class BVHObjectSplit +{ +public: + float sah; + int dim; + int num_left; + BoundBox left_bounds; + BoundBox right_bounds; + + BVHObjectSplit() {} + BVHObjectSplit(BVHBuild *builder, const BVHRange& range, float nodeSAH); + + void split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range); +}; + +/* Spatial Split */ + +class BVHSpatialSplit +{ +public: + float sah; + int dim; + float pos; + + BVHSpatialSplit() : sah(FLT_MAX), dim(0), pos(0.0f) {} + BVHSpatialSplit(BVHBuild *builder, const BVHRange& range, float nodeSAH); + + void split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range); + void split_reference(BVHBuild *builder, BVHReference& left, BVHReference& right, const BVHReference& ref, int dim, float pos); +}; + +/* Mixed Object-Spatial Split */ + +class BVHMixedSplit +{ +public: + BVHObjectSplit object; + BVHSpatialSplit spatial; + + float leafSAH; + float nodeSAH; + float minSAH; + + bool no_split; + + __forceinline BVHMixedSplit(BVHBuild *builder, const BVHRange& range, int level) + { + /* find split candidates. */ + float area = range.bounds().safe_area(); + + leafSAH = area * builder->params.triangle_cost(range.size()); + nodeSAH = area * builder->params.node_cost(2); + + object = BVHObjectSplit(builder, range, nodeSAH); + + if(builder->params.use_spatial_split && level < BVHParams::MAX_SPATIAL_DEPTH) { + BoundBox overlap = object.left_bounds; + overlap.intersect(object.right_bounds); + + if(overlap.safe_area() >= builder->spatial_min_overlap) + spatial = BVHSpatialSplit(builder, range, nodeSAH); + } + + /* leaf SAH is the lowest => create leaf. */ + minSAH = min(min(leafSAH, object.sah), spatial.sah); + no_split = (minSAH == leafSAH && range.size() <= builder->params.max_leaf_size); + } + + __forceinline void split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range) + { + if(builder->params.use_spatial_split && minSAH == spatial.sah) + spatial.split(builder, left, right, range); + if(!left.size() || !right.size()) + object.split(builder, left, right, range); + } +}; + +CCL_NAMESPACE_END + +#endif /* __BVH_SPLIT_H__ */ + diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index a7eb365f983..0ce16e65621 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -43,6 +43,7 @@ Mesh::Mesh() transform_applied = false; transform_negative_scaled = false; displacement_method = DISPLACE_BUMP; + bounds = BoundBox::empty; bvh = NULL; @@ -96,7 +97,7 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_) void Mesh::compute_bounds() { - BoundBox bnds; + BoundBox bnds = BoundBox::empty; size_t verts_size = verts.size(); for(size_t i = 0; i < verts_size; i++) @@ -697,6 +698,8 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen progress.set_status(msg, "Building BVH"); mesh->compute_bvh(&scene->params, progress); + + i++; } if(progress.get_cancel()) return; @@ -704,8 +707,6 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen mesh->need_update = false; mesh->need_update_rebuild = false; } - - i++; } foreach(Shader *shader, scene->shaders) diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 5f7a5810c09..28645d856a8 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -37,6 +37,7 @@ Object::Object() tfm = transform_identity(); visibility = ~0; pass_id = 0; + bounds = BoundBox::empty; } Object::~Object() diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp index ff477296c7e..f6acc358959 100644 --- a/intern/cycles/subd/subd_patch.cpp +++ b/intern/cycles/subd/subd_patch.cpp @@ -93,7 +93,7 @@ void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float BoundBox LinearQuadPatch::bound() { - BoundBox bbox; + BoundBox bbox = BoundBox::empty; for(int i = 0; i < 4; i++) bbox.grow(hull[i]); @@ -115,7 +115,7 @@ void LinearTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, f BoundBox LinearTrianglePatch::bound() { - BoundBox bbox; + BoundBox bbox = BoundBox::empty; for(int i = 0; i < 3; i++) bbox.grow(hull[i]); @@ -132,7 +132,7 @@ void BicubicPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v) BoundBox BicubicPatch::bound() { - BoundBox bbox; + BoundBox bbox = BoundBox::empty; for(int i = 0; i < 16; i++) bbox.grow(hull[i]); @@ -152,7 +152,7 @@ void BicubicTangentPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, f BoundBox BicubicTangentPatch::bound() { - BoundBox bbox; + BoundBox bbox = BoundBox::empty; for(int i = 0; i < 16; i++) bbox.grow(hull[i]); @@ -205,7 +205,7 @@ void GregoryQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, floa BoundBox GregoryQuadPatch::bound() { - BoundBox bbox; + BoundBox bbox = BoundBox::empty; for(int i = 0; i < 20; i++) bbox.grow(hull[i]); @@ -276,7 +276,7 @@ void GregoryTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, BoundBox GregoryTrianglePatch::bound() { - BoundBox bbox; + BoundBox bbox = BoundBox::empty; for(int i = 0; i < 20; i++) bbox.grow(hull[i]); diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h index bb1df0b220f..2c0f38c44a6 100644 --- a/intern/cycles/util/util_boundbox.h +++ b/intern/cycles/util/util_boundbox.h @@ -35,45 +35,81 @@ class BoundBox public: float3 min, max; - BoundBox(void) + __forceinline BoundBox() { - min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX); - max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX); } - BoundBox(const float3& min_, const float3& max_) + __forceinline BoundBox(const float3& pt) + : min(pt), max(pt) + { + } + + __forceinline BoundBox(const float3& min_, const float3& max_) : min(min_), max(max_) { } - void grow(const float3& pt) + static struct empty_t {} empty; + + __forceinline BoundBox(empty_t) + : min(make_float3(FLT_MAX, FLT_MAX, FLT_MAX)), max(make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX)) + { + } + + __forceinline void grow(const float3& pt) { min = ccl::min(min, pt); max = ccl::max(max, pt); } - void grow(const BoundBox& bbox) + __forceinline void grow(const BoundBox& bbox) { grow(bbox.min); grow(bbox.max); } - void intersect(const BoundBox& bbox) + __forceinline void intersect(const BoundBox& bbox) { min = ccl::max(min, bbox.min); max = ccl::min(max, bbox.max); } - float area(void) const + /* todo: avoid using this */ + __forceinline float safe_area() const { - if(!valid()) + if(!((min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z))) return 0.0f; - float3 d = max - min; - return dot(d, d)*2.0f; + return area(); } - bool valid(void) const + __forceinline float area() const + { + return half_area()*2.0f; + } + + __forceinline float half_area() const + { + float3 d = max - min; + return (d.x*d.z + d.y*d.z + d.x*d.y); + } + + __forceinline float3 center() const + { + return 0.5f*(min + max); + } + + __forceinline float3 center2() const + { + return min + max; + } + + __forceinline float3 size() const + { + return max - min; + } + + __forceinline bool valid() const { return (min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z) && (isfinite(min.x) && isfinite(min.y) && isfinite(min.z)) && @@ -82,7 +118,7 @@ public: BoundBox transformed(const Transform *tfm) { - BoundBox result; + BoundBox result = BoundBox::empty; for(int i = 0; i < 8; i++) { float3 p; @@ -98,6 +134,31 @@ public: } }; +__forceinline BoundBox merge(const BoundBox& bbox, const float3& pt) +{ + return BoundBox(min(bbox.min, pt), max(bbox.max, pt)); +} + +__forceinline BoundBox merge(const BoundBox& a, const BoundBox& b) +{ + return BoundBox(min(a.min, b.min), max(a.max, b.max)); +} + +__forceinline BoundBox merge(const BoundBox& a, const BoundBox& b, const BoundBox& c, const BoundBox& d) +{ + return merge(merge(a, b), merge(c, d)); +} + +__forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b) +{ + return BoundBox(max(a.min, b.min), min(a.max, b.max)); +} + +__forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b, const BoundBox& c) +{ + return intersect(a, intersect(b, c)); +} + CCL_NAMESPACE_END #endif /* __UTIL_BOUNDBOX_H__ */ From 9be1c5c009c51a304dc11a98df628782e4cdabd0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 24 Apr 2012 12:01:24 +0000 Subject: [PATCH 013/183] Cycles: cuda build fix. --- intern/cycles/util/util_math.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 8768c798d16..d9e4d4fbac9 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -680,6 +680,10 @@ __device_inline float4 max(float4 a, float4 b) return make_float4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w)); } +#endif + +#ifndef __KERNEL_GPU__ + __device_inline float4 select(const int4& mask, const float4& a, const float4& b) { return make_float4((mask.x)? a.x: b.x, (mask.y)? a.y: b.y, (mask.z)? a.z: b.z, (mask.w)? a.w: b.w); @@ -705,10 +709,6 @@ __device_inline float3 rcp(const float3& a) return make_float3(1.0f/a.x, 1.0f/a.y, 1.0f/a.z); } -#endif - -#ifndef __KERNEL_GPU__ - __device_inline void print_float4(const char *label, const float4& a) { printf("%s: %.8f %.8f %.8f %.8f\n", label, a.x, a.y, a.z, a.w); From 40e58dbca98898c8dd7db16eb6cfce17137a02fa Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 24 Apr 2012 14:59:08 +0000 Subject: [PATCH 014/183] Cycles: * Fixing wrong windows define, causing compile errors. --- intern/cycles/util/util_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index b6c57e3eb6e..da9e68300a6 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -36,7 +36,7 @@ #define __shared #define __constant -#ifdef __WIN32__ +#ifdef _WIN32 #define __device_inline static __forceinline #define __align(...) __declspec(align(__VA_ARGS__)) #else From effc0d352e08e579dbab3d7d880951be8a683351 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 24 Apr 2012 17:56:27 +0000 Subject: [PATCH 015/183] Cycles: attempted BVH binning build fix for windows. --- intern/cycles/bvh/bvh_binning.cpp | 2 ++ intern/cycles/util/util_boundbox.h | 1 + 2 files changed, 3 insertions(+) diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp index def5309e551..8286e15b5c6 100644 --- a/intern/cycles/bvh/bvh_binning.cpp +++ b/intern/cycles/bvh/bvh_binning.cpp @@ -15,6 +15,8 @@ * limitations under the License. */ +#include + #include "bvh_binning.h" #include "util_algorithm.h" diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h index 2c0f38c44a6..9511b48e103 100644 --- a/intern/cycles/util/util_boundbox.h +++ b/intern/cycles/util/util_boundbox.h @@ -23,6 +23,7 @@ #include #include "util_math.h" +#include "util_string.h" #include "util_transform.h" #include "util_types.h" From 713de1b1f4639895a8edcb71d9bb3d8e16f0a15f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 24 Apr 2012 17:59:57 +0000 Subject: [PATCH 016/183] Point Cache: allow baking external smoke caches. This needs to be cleaned up a bit, I couldn't fully understand how the External setting is supposed to work to make further changes, but this should make it work at least. --- .../bl_ui/properties_physics_common.py | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py index f623d9a37eb..4db056e77a2 100644 --- a/release/scripts/startup/bl_ui/properties_physics_common.py +++ b/release/scripts/startup/bl_ui/properties_physics_common.py @@ -94,18 +94,25 @@ def point_cache_ui(self, context, cache, enabled, cachetype): if cachetype in {'PSYS', 'HAIR', 'SMOKE'}: row.prop(cache, "use_external") + if cachetype == 'SMOKE': + row.prop(cache, "use_library_path", "Use Lib Path") + if cache.use_external: - split = layout.split(percentage=0.80) - split.prop(cache, "name", text="File Name") - split.prop(cache, "index", text="") + split = layout.split(percentage=0.35) + col = split.column() + col.label(text="File Name:") + if cache.use_external: + col.label(text="File Path:") - row = layout.row() - row.label(text="File Path:") - row.prop(cache, "use_library_path", "Use Lib Path") + col = split.column() + sub = col.split(percentage=0.70, align=True) + sub.prop(cache, "name", text="") + sub.prop(cache, "index", text="") + col.prop(cache, "filepath", text="") - layout.prop(cache, "filepath", text="") - - layout.label(text=cache.info) + cache_info = cache.info + if cache_info: + layout.label(text=cache_info) else: if cachetype in {'SMOKE', 'DYNAMIC_PAINT'}: if not bpy.data.is_saved: @@ -117,6 +124,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype): else: layout.prop(cache, "name", text="Cache Name") + if not cache.use_external or cachetype == 'SMOKE': row = layout.row(align=True) if cachetype not in {'PSYS', 'DYNAMIC_PAINT'}: From d40da2c9023c1bdd8f5e33e8fbe7ad6c1e2e9295 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 24 Apr 2012 19:08:26 +0000 Subject: [PATCH 017/183] Cycles: more attempts to fix windows build for BVH binning. --- intern/cycles/util/util_types.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index da9e68300a6..3c61d1f468b 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -47,6 +47,12 @@ #endif +/* Bitness */ + +#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64) +#define __KERNEL_64_BIT__ +#endif + /* SIMD Types */ /* not enabled yet, just testing */ @@ -103,6 +109,12 @@ typedef unsigned int uint32_t; typedef long long int64_t; typedef unsigned long long uint64_t; +#ifdef __KERNEL_64_BIT__ +typedef int64_t ssize_t; +#else +typedef int32_t ssize_t; +#endif + #endif /* Generic Memory Pointer */ From a49a64b7108e1016d84c2063d7ea93b3e5a8cc54 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 28 Apr 2012 14:40:37 +0000 Subject: [PATCH 018/183] Camera tracking: small improvements to tripod solver" - Disable camera refirement due to it's not only refines camera intrinsics but also adjusts camera position which isn't necessary here - Detect rigid transformation between initial frame and current instead of detecting it between two neighbour frames. This prevents accumulation of error and seems to be working better in footages i've tested. --- extern/libmv/libmv-capi.cpp | 7 +------ extern/libmv/libmv-capi.h | 2 +- extern/libmv/libmv/simple_pipeline/modal_solver.cc | 10 +++------- release/scripts/startup/bl_ui/space_clip.py | 2 +- source/blender/blenkernel/intern/tracking.c | 1 - 5 files changed, 6 insertions(+), 16 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 3f697d487b6..6c20d76eeac 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -460,7 +460,7 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra return (libmv_Reconstruction *)libmv_reconstruction; } -struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, int refine_intrinsics, double focal_length, +struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, reconstruct_progress_update_cb progress_update_callback, void *callback_customdata) { @@ -488,11 +488,6 @@ struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, int r libmv::ModalSolver(normalized_tracks, reconstruction, &update_callback); - if (refine_intrinsics) { - libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, intrinsics, reconstruction, - refine_intrinsics, progress_update_callback, callback_customdata); - } - progress_update_callback(callback_customdata, 1.0, "Finishing solution"); libmv_reconstruction->tracks = *(libmv::Tracks *)tracks; libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics); diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index f72a72d494b..bccc4706832 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -68,7 +68,7 @@ int libmv_refineParametersAreValid(int parameters); struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2, int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, reconstruct_progress_update_cb progress_update_callback, void *callback_customdata); -struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, int refine_intrinsics, double focal_length, +struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, reconstruct_progress_update_cb progress_update_callback, void *callback_customdata); int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]); diff --git a/extern/libmv/libmv/simple_pipeline/modal_solver.cc b/extern/libmv/libmv/simple_pipeline/modal_solver.cc index ede0071dc64..bb49b30dbce 100644 --- a/extern/libmv/libmv/simple_pipeline/modal_solver.cc +++ b/extern/libmv/libmv/simple_pipeline/modal_solver.cc @@ -91,19 +91,15 @@ void ModalSolver(Tracks &tracks, ProjectMarkerOnSphere(marker, X); - points.push_back(R * point->X); + points.push_back(point->X); reference_points.push_back(X); } } } if (points.size()) { - Mat3 dR = Mat3::Identity(); - - // Find rigid delta transformation from previous image to current image - RigidRegistration(reference_points, points, dR); - - R *= dR; + // Find rigid delta transformation to current image + RigidRegistration(reference_points, points, R); } reconstruction->InsertCamera(image, R, Vec3::Zero()); diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index fb84fa29cbc..e4f608e2660 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -256,7 +256,7 @@ class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel): col.prop(settings, "keyframe_b") col = layout.column(align=True) - col.active = tracking_object.is_camera + col.active = tracking_object.is_camera and not settings.use_tripod_solver col.label(text="Refine:") col.prop(settings, "refine_intrinsics", text="") diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 9e3bc2648a5..e511cd362de 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1902,7 +1902,6 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short * if (context->motion_flag & TRACKING_MOTION_MODAL) { context->reconstruction = libmv_solveModal(context->tracks, - context->refine_flags, context->focal_length, context->principal_point[0], context->principal_point[1], context->k1, context->k2, context->k3, From 1e73bf60f9c20e54158756e021cf98fb9368a2f7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 29 Apr 2012 11:16:40 +0000 Subject: [PATCH 019/183] - Synchronize with changes in trunk - Reverted parts of recent trunk merge related on changes for preview image save skip needed for startup.blend generation --- source/blender/blenloader/intern/writefile.c | 4 ++-- source/blender/editors/space_clip/space_clip.c | 2 +- source/blender/windowmanager/intern/wm_files.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 5f8e4841d2d..42736b6b787 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1867,7 +1867,7 @@ static void write_previews(WriteData *wd, PreviewImage *prv) short h = prv->h[1]; unsigned int *rect = prv->rect[1]; /* don't write out large previews if not requested */ - if (!(U.flag & USER_SAVE_PREVIEWS) || TRUE) { + if (!(U.flag & USER_SAVE_PREVIEWS)) { prv->w[1] = 0; prv->h[1] = 0; prv->rect[1] = NULL; @@ -1877,7 +1877,7 @@ static void write_previews(WriteData *wd, PreviewImage *prv) if (prv->rect[1]) writedata(wd, DATA, prv->w[1]*prv->h[1]*sizeof(unsigned int), prv->rect[1]); /* restore preview, we still want to keep it in memory even if not saved to file */ - if (!(U.flag & USER_SAVE_PREVIEWS) || TRUE) { + if (!(U.flag & USER_SAVE_PREVIEWS) ) { prv->w[1] = w; prv->h[1] = h; prv->rect[1] = rect; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 8339bc14cdd..9a5a7120a3d 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -315,7 +315,7 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) /* clear or remove stuff from old */ scn->scopes.track_preview = NULL; - scn->scopes.ok = 0; + scn->scopes.ok = FALSE; scn->draw_context = NULL; return (SpaceLink *)scn; diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 7f5271e5ffa..e50fbaa624e 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -787,7 +787,7 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re /* blend file thumbnail */ /* save before exit_editmode, otherwise derivedmeshes for shared data corrupt #27765) */ - if ((U.flag & USER_SAVE_PREVIEWS) && 0) { + if (U.flag & USER_SAVE_PREVIEWS) { ibuf_thumb = blend_file_thumb(CTX_data_scene(C), CTX_wm_screen(C), &thumb); } From f8e134db13d9cf7e0e1ef00802f87bbed46c208c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 29 Apr 2012 15:30:54 +0000 Subject: [PATCH 020/183] Tomato branch: correction to dopesheet background color versioning check --- source/blender/editors/interface/resources.c | 2 +- source/blender/editors/space_clip/clip_dopesheet_draw.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 26b0d13e10b..b2aff51006e 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1778,7 +1778,7 @@ void init_userdef_do_versions(void) } } - if (bmain->versionfile < 262 || (bmain->versionfile == 262 && bmain->subversionfile < 5)) { + { bTheme *btheme; for (btheme = U.themes.first; btheme; btheme = btheme->next) { if (btheme->tclip.strip[0] == 0) { diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 3da5ec10582..c64ead91589 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -194,7 +194,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) track_channel_color(track, default_color, color); glColor4fv(color); - glRectf(v2d->cur.xmin, (float)y - CHANNEL_HEIGHT_HALF, + glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); } @@ -228,7 +228,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) else glColor4fv(strip); - glRectf(start_marker->framenr, (float)y - STRIP_HEIGHT_HALF, + glRectf(start_marker->framenr, (float) y - STRIP_HEIGHT_HALF, start_marker->framenr + len, (float) y + STRIP_HEIGHT_HALF); draw_keyframe_shape(start_marker->framenr, y, xscale, yscale, sel, alpha); @@ -318,7 +318,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) track_channel_color(track, NULL, color); glColor3fv(color); - glRectf(v2d->cur.xmin, (float)y - CHANNEL_HEIGHT_HALF, + glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); if (sel) From ebbc038e4f044be9f2c5f495bce685fb267d99cf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 29 Apr 2012 16:56:56 +0000 Subject: [PATCH 021/183] Tomato: fixed opengl issue with intel cards Issue was caused by some mixes of glRect called to draw zero-width rectangles and glCalllist. Resolved by not using glRect if rectangle is "degenerated". --- .../editors/space_clip/clip_dopesheet_draw.c | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index c64ead91589..758a2ac3d99 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -108,7 +108,7 @@ static void draw_keyframe_shape(float x, float y, float xscale, float yscale, sh if (displist2 == 0) { displist2 = glGenLists(1); glNewList(displist2, GL_COMPILE); - + glBegin(GL_QUADS); glVertex2fv(_unit_diamond_shape[0]); glVertex2fv(_unit_diamond_shape[1]); @@ -180,8 +180,8 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) continue; /* check if visible */ - if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || - IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { float alpha; int i, sel = track->flag & TRACK_DOPE_SEL; @@ -228,11 +228,15 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) else glColor4fv(strip); - glRectf(start_marker->framenr, (float) y - STRIP_HEIGHT_HALF, - start_marker->framenr + len, (float) y + STRIP_HEIGHT_HALF); - - draw_keyframe_shape(start_marker->framenr, y, xscale, yscale, sel, alpha); - draw_keyframe_shape(start_marker->framenr + len, y, xscale, yscale, sel, alpha); + if (len) { + glRectf(start_marker->framenr, (float) y - STRIP_HEIGHT_HALF, + start_marker->framenr + len, (float) y + STRIP_HEIGHT_HALF); + draw_keyframe_shape(start_marker->framenr, y, xscale, yscale, sel, alpha); + draw_keyframe_shape(start_marker->framenr + len, y, xscale, yscale, sel, alpha); + } + else { + draw_keyframe_shape(start_marker->framenr, y, xscale, yscale, sel, alpha); + } } i++; @@ -309,8 +313,8 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) continue; /* check if visible */ - if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || - IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { float font_height, color[3]; int sel = track->flag & TRACK_DOPE_SEL; @@ -349,8 +353,8 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) continue; /* check if visible */ - if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || - IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { uiBut *but; PointerRNA ptr; From ebe4ffa8de3c0a2d471e6f859e96921fe95b475b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 29 Apr 2012 20:04:12 +0000 Subject: [PATCH 022/183] Tomato: refactoring of dopesheet to allow different sort orders in list of channels Store list of channels displaying in dopesheet separately from list of tracks. This allows to re-sort channels in dopesheet independently from list of all tracks (currently only alphabetic sorting is implemented). This also allows to cache assorted information (like tracked segments of track) but currently such a things are not bottlenecks and could be done after merge dopesheet view into trunk. TODO: - Still have some deadlocks when drawing selected channels. Skipping channel background or keyframe drawing helps here but this need to be resolved. - Bump sub-version and wrote code needed to convert pre-dopesheet interface with opened curve view displaying properly. - Probably it'll worth caching tracked segments. --- source/blender/blenkernel/BKE_tracking.h | 3 + source/blender/blenkernel/intern/movieclip.c | 2 +- source/blender/blenkernel/intern/tracking.c | 60 +++++++++++++++++++ source/blender/blenloader/intern/readfile.c | 16 +++++ source/blender/blenloader/intern/writefile.c | 14 +++++ source/blender/editors/include/ED_clip.h | 2 + .../editors/space_clip/clip_dopesheet_draw.c | 33 ++++------ .../editors/space_clip/clip_dopesheet_ops.c | 30 +++------- .../blender/editors/space_clip/clip_editor.c | 8 +++ .../editors/space_clip/clip_graph_ops.c | 5 -- .../blender/editors/space_clip/tracking_ops.c | 17 ++++++ source/blender/makesdna/DNA_tracking_types.h | 13 ++++ 12 files changed, 156 insertions(+), 47 deletions(-) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 2bb8fc691f0..3b1a5dbfc8a 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -164,6 +164,9 @@ struct MovieTrackingObject *BKE_tracking_named_object(struct MovieTracking *trac void BKE_tracking_select_track(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, int extend); void BKE_tracking_deselect_track(struct MovieTrackingTrack *track, int area); +/* Dopesheet */ +void BKE_tracking_update_dopesheet(struct MovieTracking *tracking); + #define TRACK_SELECTED(track) ((track)->flag&SELECT || (track)->pat_flag&SELECT || (track)->search_flag&SELECT) #define TRACK_AREA_SELECTED(track, area) ((area)==TRACK_AREA_POINT ? (track)->flag&SELECT : \ diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index d548d7589bb..0fd3a9eb753 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -453,7 +453,7 @@ static MovieClip *movieclip_alloc(const char *name) MovieClip *BKE_movieclip_file_add(const char *name) { MovieClip *clip; - MovieClipUser user; + MovieClipUser user = {0}; int file, len, width, height; const char *libname; char str[FILE_MAX], strtest[FILE_MAX]; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index e511cd362de..316cb4b6159 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -632,6 +632,12 @@ static void tracking_objects_free(ListBase *objects) BLI_freelistN(objects); } +static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet) +{ + BLI_freelistN(&dopesheet->channels); + dopesheet->tot_channel = 0; +} + void BKE_tracking_free(MovieTracking *tracking) { tracking_tracks_free(&tracking->tracks); @@ -643,6 +649,8 @@ void BKE_tracking_free(MovieTracking *tracking) if (tracking->camera.intrinsics) BKE_tracking_distortion_destroy(tracking->camera.intrinsics); + + tracking_dopesheet_free(&tracking->dopesheet); } static MovieTrackingTrack *duplicate_track(MovieTrackingTrack *track) @@ -1352,6 +1360,8 @@ void BKE_tracking_sync(MovieTrackingContext *context) newframe = context->user.framenr - 1; context->sync_frame = newframe; + + BKE_tracking_update_dopesheet(tracking); } void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context) @@ -3033,3 +3043,53 @@ MovieTrackingObject *BKE_tracking_named_object(MovieTracking *tracking, const ch return NULL; } + +/*********************** dopesheet functions *************************/ + +static int channels_alpha_sort(void *a, void *b) +{ + MovieTrackingDopesheetChannel *channel_a = a; + MovieTrackingDopesheetChannel *channel_b = b; + + if (BLI_strcasecmp(channel_a->track->name, channel_b->track->name) > 0) + return 1; + else + return 0; +} + +void BKE_tracking_update_dopesheet(MovieTracking *tracking) +{ + MovieTrackingObject *object = BKE_tracking_active_object(tracking); + MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; + MovieTrackingTrack *track; + ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); + ListBase old_channels; + + old_channels = dopesheet->channels; + dopesheet->channels.first = dopesheet->channels.last = NULL; + dopesheet->tot_channel = 0; + + for (track = tracksbase->first; track; track = track->next) { + if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) { + MovieTrackingDopesheetChannel *channel, *old_channel; + + channel = MEM_callocN(sizeof(MovieTrackingDopesheetChannel), "tracking dopesheet channel"); + channel->track = track; + + /* copy flags from current dopsheet information to new one */ + for (old_channel = old_channels.first; old_channel; old_channel = old_channel->next) { + if (old_channel->track == track) { + channel->flag = old_channel->flag; + break; + } + } + + BLI_addtail(&dopesheet->channels, channel); + dopesheet->tot_channel++; + } + } + + BLI_sortlist(&dopesheet->channels, channels_alpha_sort); + + BLI_freelistN(&old_channels); +} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c54daed8139..f13b6ebecdc 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6167,6 +6167,20 @@ static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase) } } +static void direct_link_movieDopesheet(FileData *fd, MovieTrackingDopesheet *dopesheet) +{ + MovieTrackingDopesheetChannel *channel; + + link_list(fd, &dopesheet->channels); + + channel = dopesheet->channels.first; + while (channel) { + channel->track = newdataadr(fd, channel->track); + + channel = channel->next; + } +} + static void direct_link_movieclip(FileData *fd, MovieClip *clip) { MovieTracking *tracking= &clip->tracking; @@ -6202,6 +6216,8 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) object= object->next; } + + direct_link_movieDopesheet(fd, &clip->tracking.dopesheet); } static void lib_link_movieclip(FileData *fd, Main *main) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 42736b6b787..e74498a59aa 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2677,6 +2677,18 @@ static void write_movieTracks(WriteData *wd, ListBase *tracks) } } +static void write_movieDopesheet(WriteData *wd, MovieTrackingDopesheet *dopesheet) +{ + MovieTrackingDopesheetChannel *channel; + + channel = dopesheet->channels.first; + while (channel) { + writestruct(wd, DATA, "MovieTrackingDopesheetChannel", 1, channel); + + channel = channel->next; + } +} + static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction *reconstruction) { if (reconstruction->camnr) @@ -2709,6 +2721,8 @@ static void write_movieclips(WriteData *wd, ListBase *idbase) object= object->next; } + + write_movieDopesheet(wd, &tracking->dopesheet); } clip= clip->id.next; diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 24d9fd3a297..db6d9bbd013 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -69,6 +69,8 @@ void ED_space_clip_free_texture_buffer(struct SpaceClip *sc); int ED_space_clip_show_trackedit(struct SpaceClip *sc); +void ED_space_clip_update_dopesheet(struct SpaceClip *sc); + /* clip_ops.c */ void ED_operatormacros_clip(void); diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 758a2ac3d99..d1733cf322b 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -154,8 +154,8 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) if (clip) { MovieTracking *tracking = &clip->tracking; - MovieTrackingTrack *track; - ListBase *tracksbase = BKE_tracking_get_tracks(tracking); + MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; + MovieTrackingDopesheetChannel *channel; float y, xscale, yscale; float strip[4], selected_strip[4]; @@ -172,17 +172,15 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) glEnable(GL_BLEND); - for (track = tracksbase->first; track; track = track->next) { + for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float) (y - CHANNEL_HEIGHT_HALF); float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); - if (!TRACK_VIEW_SELECTED(sc, track)) - continue; - /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { + MovieTrackingTrack *track = channel->track; float alpha; int i, sel = track->flag & TRACK_DOPE_SEL; @@ -272,21 +270,20 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) View2D *v2d = &ar->v2d; MovieClip *clip = ED_space_clip(sc); MovieTracking *tracking; - MovieTrackingTrack *track; - ListBase *tracksbase; + MovieTrackingDopesheet *dopesheet; + MovieTrackingDopesheetChannel *channel; uiStyle *style = UI_GetStyle(); uiBlock *block; int fontid = style->widget.uifont_id; - int items, height; + int height; float y; if (!clip) return; tracking = &clip->tracking; - tracksbase = BKE_tracking_get_tracks(tracking); - items = BLI_countlist(tracksbase); - height = (items * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2); + dopesheet = &tracking->dopesheet; + height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2); if (height > (v2d->mask.ymax - v2d->mask.ymin)) { /* don't use totrect set, as the width stays the same @@ -305,17 +302,15 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) BLF_size(fontid, 11.0f, U.dpi); - for (track = tracksbase->first; track; track = track->next) { + for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float) (y - CHANNEL_HEIGHT_HALF); float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); - if (!TRACK_VIEW_SELECTED(sc, track)) - continue; - /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { + MovieTrackingTrack *track = channel->track; float font_height, color[3]; int sel = track->flag & TRACK_DOPE_SEL; @@ -345,17 +340,15 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) y = (float) CHANNEL_FIRST; glEnable(GL_BLEND); - for (track = tracksbase->first; track; track = track->next) { + for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float)(y - CHANNEL_HEIGHT_HALF); float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF); - if (!TRACK_VIEW_SELECTED(sc, track)) - continue; - /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { + MovieTrackingTrack *track = channel->track; uiBut *but; PointerRNA ptr; int icon; diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c index 2225f01afe3..bec030f5e21 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_ops.c +++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c @@ -91,40 +91,28 @@ static int dopesheet_select_channel_exec(bContext *C, wmOperator *op) SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip(sc); MovieTracking *tracking = &clip->tracking; - ListBase *tracksbase = BKE_tracking_get_tracks(tracking); - MovieTrackingTrack *track; + MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; + MovieTrackingDopesheetChannel *channel; float location[2]; - int extend = RNA_boolean_get(op->ptr, "extend"), channel, channel_index; + int extend = RNA_boolean_get(op->ptr, "extend"); + int current_channel_index = 0, channel_index; RNA_float_get_array(op->ptr, "location", location); - channel = -(location[1] - (CHANNEL_FIRST + CHANNEL_HEIGHT_HALF)) / CHANNEL_STEP; + channel_index = -(location[1] - (CHANNEL_FIRST + CHANNEL_HEIGHT_HALF)) / CHANNEL_STEP; - for (track = tracksbase->first, channel_index = 0; track; track = track->next) { - if (!TRACK_VIEW_SELECTED(sc, track)) - continue; + for (channel = dopesheet->channels.first; channel; channel = channel->next) { + MovieTrackingTrack *track = channel->track; - if (channel_index == channel) { + if (current_channel_index == channel_index) { if (extend) track->flag ^= TRACK_DOPE_SEL; else track->flag |= TRACK_DOPE_SEL; - - if (track->flag & TRACK_DOPE_SEL) { - MovieTrackingMarker *marker; - - /* make last selected in dopesheet track active in clip editor */ - tracking->act_track = track; - - /* make active track be centered to screen */ - /* XXX: doesn't work in other opened spaces */ - marker = BKE_tracking_get_marker(track, sc->user.framenr); - clip_view_center_to_point(sc, marker->pos[0], marker->pos[1]); - } } else if (!extend) track->flag &= ~TRACK_DOPE_SEL; - channel_index++; + current_channel_index++; } WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 69a8b0f4c92..e61580295fc 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -565,3 +565,11 @@ int ED_space_clip_show_trackedit(SpaceClip *sc) return FALSE; } + +void ED_space_clip_update_dopesheet(SpaceClip *sc) +{ + MovieClip *clip = sc->clip; + MovieTracking *tracking = &clip->tracking; + + BKE_tracking_update_dopesheet(tracking); +} diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index 7ab41078e16..0414c969705 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -234,11 +234,6 @@ static int mouse_select_curve(bContext *C, float co[2], int extend) tracking->act_track = userdata.track; - /* make active track be centered to screen */ - /* XXX: doesn't work in other opened spaces */ - marker = BKE_tracking_get_marker(userdata.track, sc->user.framenr); - clip_view_center_to_point(sc, marker->pos[0], marker->pos[1]); - /* deselect all knots on newly selected curve */ clip_graph_tracking_iterate(sc, &selectdata, toggle_selection_cb); } diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index b3bb7464761..2c9b61ed1ef 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -95,6 +95,8 @@ static void add_marker(SpaceClip *sc, float x, float y) BKE_tracking_select_track(tracksbase, track, TRACK_AREA_ALL, 0); clip->tracking.act_track = track; + + ED_space_clip_update_dopesheet(sc); } static int add_marker_exec(bContext *C, wmOperator *op) @@ -174,6 +176,8 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op)) /* nothing selected now, unlock view so it can be scrolled nice again */ sc->flag &= ~SC_LOCK_SELECTION; + ED_space_clip_update_dopesheet(sc); + return OPERATOR_FINISHED; } @@ -225,6 +229,8 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op)) sc->flag &= ~SC_LOCK_SELECTION; } + ED_space_clip_update_dopesheet(sc); + return OPERATOR_FINISHED; } @@ -790,6 +796,7 @@ static int mouse_select(bContext *C, float co[2], int extend) } WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL); + ED_space_clip_update_dopesheet(sc); return OPERATOR_FINISHED; } @@ -901,6 +908,8 @@ static int border_select_exec(bContext *C, wmOperator *op) } if (change) { + ED_space_clip_update_dopesheet(sc); + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL); return OPERATOR_FINISHED; @@ -985,6 +994,8 @@ static int circle_select_exec(bContext *C, wmOperator *op) } if (change) { + ED_space_clip_update_dopesheet(sc); + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL); return OPERATOR_FINISHED; @@ -1081,6 +1092,8 @@ static int select_all_exec(bContext *C, wmOperator *op) if (!has_selection) sc->flag &= ~SC_LOCK_SELECTION; + ED_space_clip_update_dopesheet(sc); + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL); return OPERATOR_FINISHED; @@ -1161,6 +1174,8 @@ static int select_groped_exec(bContext *C, wmOperator *op) track = track->next; } + ED_space_clip_update_dopesheet(sc); + WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, clip); return OPERATOR_FINISHED; @@ -2730,6 +2745,8 @@ static int hide_tracks_exec(bContext *C, wmOperator *op) sc->flag &= ~SC_LOCK_SELECTION; } + BKE_tracking_update_dopesheet(tracking); + WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 84d4215401b..e8abee36716 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -193,6 +193,17 @@ typedef struct MovieTrackingStats { char message[256]; } MovieTrackingStats; +typedef struct MovieTrackingDopesheetChannel { + struct MovieTrackingDopesheetChannel *next, *prev; + MovieTrackingTrack *track; + int flag, pad; +} MovieTrackingDopesheetChannel; + +typedef struct MovieTrackingDopesheet { + ListBase channels; + int tot_channel, pad; +} MovieTrackingDopesheet; + typedef struct MovieTracking { MovieTrackingSettings settings; /* different tracking-related settings */ MovieTrackingCamera camera; /* camera intrinsics */ @@ -205,6 +216,8 @@ typedef struct MovieTracking { int objectnr, tot_object; /* index of active object and total number of objects */ MovieTrackingStats *stats; /* statistics displaying in clip editor */ + + MovieTrackingDopesheet dopesheet; /* dopesheet data */ } MovieTracking; /* MovieTrackingCamera->units */ From 9151d46d7dbab7c978604656c146245aaf8f4ce3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Apr 2012 07:43:21 +0000 Subject: [PATCH 023/183] Tomato: initial commit of mask editing tools into SVN - Added new dtaablock called Mask which might be re-used in any area. Currently editing of masks happens in clip editor and they might be used in compositor nodes only. - Added new mode to clip clip editor to interact with masks. Implemented basic tools to create shapes, splines and points. Also implemented idea of UW points for feather which means feather points are have got U coordinate along spline (which is measured from 0 to 1) and W is it's weight meaning distance from main spline. - Spline points might be parented to movie tracks. Interface for this isn't best yet. - Rasterisaztion of masks happens in compositor node (Input -> Mask) Input image of this ode is used as reference for mask resolution. Currently all splines of all shapes are rasterizing independently which means shapes with holes are not supported. Also feather rasterization is not implemented. Rasterized was implemented by Pete Larbell, thanks! Do not consider this is something finished, there's still lots of things to be done (especially from interface and usability points of view). --- intern/CMakeLists.txt | 1 + intern/SConscript | 3 +- intern/raskter/CMakeLists.txt | 40 + intern/raskter/SConscript | 10 + intern/raskter/raskter.c | 367 ++++ intern/raskter/raskter.h | 55 + .../modules/bpy_extras/keyconfig_utils.py | 1 + release/scripts/startup/bl_ui/space_clip.py | 121 +- source/blender/CMakeLists.txt | 1 + source/blender/blenkernel/BKE_context.h | 1 + source/blender/blenkernel/BKE_library.h | 2 +- source/blender/blenkernel/BKE_main.h | 1 + source/blender/blenkernel/BKE_mask.h | 95 + source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/CMakeLists.txt | 2 + source/blender/blenkernel/intern/context.c | 5 + source/blender/blenkernel/intern/depsgraph.c | 12 + source/blender/blenkernel/intern/idcode.c | 1 + source/blender/blenkernel/intern/library.c | 11 + source/blender/blenkernel/intern/mask.c | 890 +++++++++ source/blender/blenkernel/intern/node.c | 1 + source/blender/blenkernel/intern/scene.c | 6 + source/blender/blenloader/intern/readfile.c | 91 + source/blender/blenloader/intern/writefile.c | 50 + source/blender/editors/CMakeLists.txt | 1 + source/blender/editors/SConscript | 1 + source/blender/editors/include/ED_clip.h | 9 + source/blender/editors/include/ED_mask.h | 44 + source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/include/ED_transform.h | 1 + .../editors/interface/interface_templates.c | 6 +- source/blender/editors/mask/CMakeLists.txt | 47 + source/blender/editors/mask/SConscript | 9 + source/blender/editors/mask/mask_draw.c | 270 +++ source/blender/editors/mask/mask_editor.c | 218 +++ source/blender/editors/mask/mask_intern.h | 69 + source/blender/editors/mask/mask_ops.c | 1653 +++++++++++++++++ source/blender/editors/screen/screen_ops.c | 8 + source/blender/editors/space_api/spacetypes.c | 4 + .../blender/editors/space_clip/clip_editor.c | 91 + .../blender/editors/space_clip/space_clip.c | 53 +- source/blender/editors/space_node/drawnode.c | 8 + .../blender/editors/space_node/space_node.c | 7 + source/blender/editors/transform/transform.c | 61 +- source/blender/editors/transform/transform.h | 1 + .../editors/transform/transform_conversions.c | 207 +++ .../editors/transform/transform_generics.c | 50 +- .../blender/editors/transform/transform_ops.c | 1 + source/blender/makesdna/DNA_ID.h | 1 + source/blender/makesdna/DNA_mask_types.h | 108 ++ source/blender/makesdna/DNA_space_types.h | 5 + source/blender/makesdna/intern/makesdna.c | 2 + source/blender/makesrna/RNA_access.h | 2 + source/blender/makesrna/intern/CMakeLists.txt | 1 + source/blender/makesrna/intern/makesrna.c | 1 + source/blender/makesrna/intern/rna_ID.c | 2 + source/blender/makesrna/intern/rna_internal.h | 2 + source/blender/makesrna/intern/rna_main.c | 7 + source/blender/makesrna/intern/rna_main_api.c | 51 + source/blender/makesrna/intern/rna_mask.c | 600 ++++++ source/blender/makesrna/intern/rna_nodetree.c | 12 + .../makesrna/intern/rna_nodetree_types.h | 1 + source/blender/makesrna/intern/rna_space.c | 16 + source/blender/nodes/CMakeLists.txt | 2 + source/blender/nodes/NOD_composite.h | 2 + .../nodes/composite/node_composite_tree.c | 4 + .../composite/nodes/node_composite_mask.c | 124 ++ source/blender/windowmanager/WM_types.h | 1 + source/blenderplayer/CMakeLists.txt | 1 + .../bad_level_call_stubs/stubs.c | 1 + source/creator/CMakeLists.txt | 2 + 71 files changed, 5496 insertions(+), 40 deletions(-) create mode 100644 intern/raskter/CMakeLists.txt create mode 100644 intern/raskter/SConscript create mode 100644 intern/raskter/raskter.c create mode 100644 intern/raskter/raskter.h create mode 100644 source/blender/blenkernel/BKE_mask.h create mode 100644 source/blender/blenkernel/intern/mask.c create mode 100644 source/blender/editors/include/ED_mask.h create mode 100644 source/blender/editors/mask/CMakeLists.txt create mode 100644 source/blender/editors/mask/SConscript create mode 100644 source/blender/editors/mask/mask_draw.c create mode 100644 source/blender/editors/mask/mask_editor.c create mode 100644 source/blender/editors/mask/mask_intern.h create mode 100644 source/blender/editors/mask/mask_ops.c create mode 100644 source/blender/makesdna/DNA_mask_types.h create mode 100644 source/blender/makesrna/intern/rna_mask.c create mode 100644 source/blender/nodes/composite/nodes/node_composite_mask.c diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index c85f0fddc34..71d2ef5e410 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -31,6 +31,7 @@ add_subdirectory(memutil) add_subdirectory(iksolver) add_subdirectory(opennl) add_subdirectory(mikktspace) +add_subdirectory(raskter) if(WITH_AUDASPACE) add_subdirectory(audaspace) diff --git a/intern/SConscript b/intern/SConscript index b6305f7dbab..6f08c696317 100644 --- a/intern/SConscript +++ b/intern/SConscript @@ -14,7 +14,8 @@ SConscript(['audaspace/SConscript', 'boolop/SConscript', 'opennl/SConscript', 'mikktspace/SConscript', - 'smoke/SConscript']) + 'smoke/SConscript', + 'raskter/SConscript']) # NEW_CSG was intended for intern/csg, but # getting it to compile is difficult diff --git a/intern/raskter/CMakeLists.txt b/intern/raskter/CMakeLists.txt new file mode 100644 index 00000000000..3e1368d8eb0 --- /dev/null +++ b/intern/raskter/CMakeLists.txt @@ -0,0 +1,40 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Peter Larabell +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . +) + +set(INC_SYS + +) + +set(SRC + raskter.c + + raskter.h +) + +blender_add_lib(bf_intern_raskter "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/raskter/SConscript b/intern/raskter/SConscript new file mode 100644 index 00000000000..7ad505d70e4 --- /dev/null +++ b/intern/raskter/SConscript @@ -0,0 +1,10 @@ +#!/usr/bin/python + +Import ('env') + +sources = ['raskter.c'] + +incs = '' +defs = '' + +env.BlenderLib ('bf_intern_raskter', sources, Split(incs), Split(defs), libtype=['intern'], priority=[100] ) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c new file mode 100644 index 00000000000..d5890f1741a --- /dev/null +++ b/intern/raskter/raskter.c @@ -0,0 +1,367 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Peter Larabell. + * + * ***** END GPL LICENSE BLOCK ***** + */ +/** \file raskter.c + * \ingroup RASKTER + */ + +#include +#include "raskter.h" + +#define R_XCHG(a,b) t=a;a=b;b=t; + +struct e_status { + int x; + int ybeg; + int xshift; + int xdir; + int drift; + int drift_inc; + int drift_dec; + int num; + struct e_status *e_next; +}; + +struct r_buffer_stats { + float *buf; + int sizex; + int sizey; +}; + +static struct e_status *all_edges, *possible_edges; +static struct r_buffer_stats rb; +/* + * Sort all the edges of the input polygon by Y, then by X, of the "first" vertex encountered. + * This will ensure we can scan convert the entire poly in one pass. + * + * Really the poly should be clipped to the frame buffer's dimensions here for speed of drawing + * just the poly. Since the DEM code could end up being coupled with this, we'll keep it separate + * for now. + */ +static void preprocess_all_edges(struct poly_vert * verts, int num_verts, struct e_status * open_edge) { + int i; + int xbeg; + int ybeg; + int xend; + int yend; + int dx; + int dy; + int t; + int xdist; + struct e_status *e_new; + struct e_status *next_edge; + struct e_status **next_edge_ref; + struct poly_vert *v; + // set up pointers + v = verts; + all_edges = NULL; + // loop all verts + for(i = 0; i < num_verts; i++) { + xbeg = v[i].x; + ybeg = v[i].y; + // determine starts and ends of edges, linking last vertex to first vertex + if(i == 0) { + xend = v[num_verts-1].x; + yend = v[num_verts-1].y; + } else { + xend = v[i-1].x; + yend = v[i-1].y; + } + // make sure our edges are facing the correct direction + if(ybeg > yend) { + R_XCHG(xbeg, xend); + R_XCHG(ybeg, yend); + } + // create the edge and determine it's slope (for incremental line drawing) + if((dy = yend - ybeg) != 0) { + e_new = open_edge++; + e_new->xdir = ((dx = xend - xbeg) > 0) ? 1 : -1; + xdist = (dx > 0) ? dx : -dx; + e_new->x = xbeg; + e_new->ybeg = ybeg; + e_new->num = dy; + e_new->drift_dec = dy; + if(dx >= 0) { + e_new->drift = 0; + } else { + e_new->drift = -dy + 1; + } + // calculate deltas for drawing + if(dy >= xdist) { + e_new->drift_inc = xdist; + e_new->xshift = 0; + } else { + e_new->drift_inc = xdist % dy; + e_new->xshift = (xdist / dy) * e_new->xdir; + } + next_edge_ref = &all_edges; + // link in all the edges, in sorted order + for(;;) { + next_edge = *next_edge_ref; + if((next_edge == NULL) || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) { + e_new->e_next = next_edge; + *next_edge_ref = e_new; + break; + } + next_edge_ref = &next_edge->e_next; + } + } + } +} + +/* + * This function clips drawing to the frame buffer. That clipping will likely be moved into the preprocessor + * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need + * if it ends up being coupled with this function. + */ +int rast_scan_fill(struct poly_vert * verts, int num_verts) { + int x_curr; // current pixel position in X + int y_curr; // current scan line being drawn + int yp; // y-pixel's position in frame buffer + int swixd = 0; // whether or not edges switched position in X + float *cpxl; // pixel pointers... + float *mpxl; + float *spxl; + struct e_status *e_curr; // edge pointers... + struct e_status *e_temp; + struct e_status *edgbuf; + struct e_status **edgec; + + + /* + If the number of verts specified to render as a polygon is less than 3, + return immediately. Obviously we cant render a poly with sides < 3. The + return for this we set to 1, simply so it can be distinguished from the + next place we could return, which is a failure to allocate memory. + */ + if(num_verts < 3) { + return(1); + } + + /* + Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data + multiplied by the number of edges, which is always equal to the number of verts in + a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for + the preceeding error, which was a rasterization request on a 2D poly with less than + 3 sides. + */ + if((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_verts))) == NULL) { + return(0); + } + + /* + Do some preprocessing on all edges. This constructs a table structure in memory of all + the edge properties and can "flip" some edges so sorting works correctly. + */ + preprocess_all_edges(verts, num_verts, edgbuf); + + /* + Set the pointer for tracking the edges currently in processing to NULL to make sure + we don't get some crazy value after initialization. + */ + possible_edges = NULL; + + /* + Loop through all scan lines to be drawn. Since we sorted by Y values during + preprocess_all_edges(), we can already exact values for the lowest and + highest Y values we could possibly need by induction. The preprocessing sorted + out edges by Y position, we can cycle the current edge being processed once + it runs out of Y pixels. When we have no more edges, meaning the current edge + is NULL after setting the "current" edge to be the previous current edge's + "next" edge in the Y sorted edge connection chain, we can stop looping Y values, + since we can't possibly have more scan lines if we ran out of edges. :) + + TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. + Will get changed once DEM code gets in. + */ + for(y_curr = (all_edges->ybeg > 0 ? all_edges->ybeg : 0); ((all_edges != NULL) || (possible_edges != NULL)) && (y_curr < rb.sizey); y_curr++) { + + /* + Link any edges that start on the current scan line into the list of + edges currently needed to draw at least this, if not several, scan lines. + */ + + /* + Set the current edge to the beginning of the list of edges to be rasterized + into this scan line. + + We could have lots of edge here, so iterate over all the edges needed. The + preprocess_all_edges() function sorted edges by X within each chunk of Y sorting + so we safely cycle edges to thier own "next" edges in order. + + At each iteration, make sure we still have a non-NULL edge. + */ + for(edgec = &possible_edges; (all_edges != NULL) && (all_edges->ybeg == y_curr);) { + x_curr = all_edges->x; // Set current X position. + for(;;) { // Start looping edges. Will break when edges run out. + e_curr = *edgec; // Set up a current edge pointer. + if((e_curr == NULL) || (e_curr->x >= x_curr)) { // If we have an no edge, or we need to skip some X-span, + e_temp = all_edges->e_next; // set a temp "next" edge to test. + *edgec = all_edges; // Add this edge to the list to be scanned. + all_edges->e_next = e_curr; // Set up the next edge. + edgec = &all_edges->e_next; // Set our list to the next edge's location in memory. + all_edges = e_temp; // Skip the NULL or bad X edge, set pointer to next edge. + break; // Stop looping edges (since we ran out or hit empty X span. + } else { + edgec = &e_curr->e_next; // Set the pointer to the edge list the "next" edge. + } + } + } + + /* + Determine the current scan line's offset in the pixel buffer based on its Y position. + Basically we just multiply the current scan line's Y value by the number of pixels in each line. + */ + yp = y_curr * rb.sizex; + /* + Set a "scan line pointer" in memory. The location of the buffer plus the row offset. + */ + spxl = rb.buf + (yp); + /* + Set up the current edge to the first (in X) edge. The edges which could possibly be in this + list were determined in the preceeding edge loop above. They were already sorted in X by the + initial processing function. + + At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge + we will eventually hit a NULL when the list runs out. + */ + for(e_curr = possible_edges; e_curr != NULL; e_curr = e_curr->e_next) { + /* + Calculate a span of pixels to fill on the current scan line. + + Set the current pixel pointer by adding the X offset to the scan line's start offset. + Cycle the current edge the next edge. + Set the max X value to draw to be one less than the next edge's first pixel. This way we are + sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than + one time because it's on a vertex connecting two edges) + + Then blast through all the pixels in the span, advancing the pointer and setting the color to white. + + TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, + but for now it is done here until the DEM code comes in. + */ + cpxl = spxl + (e_curr->x > 0 ? e_curr->x : 0); + e_curr = e_curr->e_next; + mpxl = spxl + (e_curr->x < rb.sizex ? e_curr->x : rb.sizex) - 1; + for(; cpxl <= mpxl; *cpxl++ = 1.0f); + } + + /* + Loop through all edges of polygon that could be hit by this scan line, + and figure out their x-intersections with the next scan line. + + Either A.) we wont have any more edges to test, or B.) we just add on the + slope delta computed in preprocessing step. Since this draws non-antialiased + polygons, we dont have fractional positions, so we only move in x-direction + when needed to get all the way to the next pixel over... + */ + for(edgec = &possible_edges; (e_curr = *edgec) != NULL;) { + if((--(e_curr->num)) == 0) { + *edgec = e_curr->e_next; + } else { + e_curr->x += e_curr->xshift; + if((e_curr->drift += e_curr->drift_inc) > 0) { + e_curr->x += e_curr->xdir; + e_curr->drift -= e_curr->drift_dec; + } + edgec = &e_curr->e_next; + } + } + /* + It's possible that some edges may have crossed during the last step, so we'll be sure + that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges + sorted by x-intersection coordinate. We'll always scan through at least once to see if + edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial + pass, then we know we need to sort by x, so then cycle through edges again and perform + the sort.- + */ + if(possible_edges != NULL) { + for(edgec = &possible_edges; (e_curr = *edgec)->e_next != NULL;) { + if(e_curr->x > e_curr->e_next->x) { + e_temp = e_curr->e_next->e_next; + *edgec = e_curr->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + swixd = 1; + } + edgec = &(*edgec)->e_next; + } + for(; swixd;) { + swixd = 0; + for(edgec = &possible_edges; (e_curr = *edgec)->e_next != NULL;) { + if(e_curr->x > e_curr->e_next->x) { + e_temp = e_curr->e_next->e_next; + *edgec = e_curr->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + swixd = 1; + } + edgec = &(*edgec)->e_next; + } + } + } + } + + free(edgbuf); + return 1; +} + +int PLX_raskterize(float * verts, int num, float * buf, int buf_x, int buf_y) { + int i; // i: Loop counter. + struct poly_vert *ply; // ply: Pointer to a list of integer buffer-space vertex coordinates. + + /* + * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert + * data structure multiplied by the number of verts. + * + * In the event of a failure to allocate the memory, return 0, so this error can + * be distinguished as a memory allocation error. + */ + if((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num))) == NULL) { + return(0); + } + + /* + * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are + * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates + * in the buffer-space coordinates passed in inside buf_x and buf_y. + * + * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel + * drawn will be 1.0f in value, there is no anti-aliasing. + */ + for(i = 0; i < num; i++) { // Loop over all verts. + ply[i].x = (verts[i<<1] * buf_x) + 0.5f; // Range expand normalized X to integer buffer-space X. + ply[i].y = (verts[(i<<1)+1] * buf_y) + 0.5f; // Range expand normalized Y to integer buffer-space Y. + } + + rb.buf = buf; // Set the output buffer pointer. + rb.sizex = buf_x; // Set the output buffer size in X. (width) + rb.sizey = buf_y; // Set the output buffer size in Y. (height) + + i = rast_scan_fill(ply, num); // Call our rasterizer, passing in the integer coords for each vert. + free(ply); // Free the memory allocated for the integer coordinate table. + return(i); // Return the value returned by the rasterizer. +} diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h new file mode 100644 index 00000000000..0b3cf365ff4 --- /dev/null +++ b/intern/raskter/raskter.h @@ -0,0 +1,55 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Peter Larabell. + * + * ***** END GPL LICENSE BLOCK ***** + */ +/** \file raskter.h + * \ingroup RASKTER + */ + +struct poly_vert{ + int x; + int y; +}; + +struct scan_line{ + int xstart; + int xend; +}; + +struct scan_line_batch{ + int num; + int ystart; + struct scan_line * slines; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int PLX_raskterize(float * verts, int num, float * buf, int buf_x, int buf_y); + +#ifdef __cplusplus +} +#endif diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py index 20b0669e531..306371ea6f5 100644 --- a/release/scripts/modules/bpy_extras/keyconfig_utils.py +++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py @@ -95,6 +95,7 @@ KM_HIERARCHY = [ ('Clip', 'CLIP_EDITOR', 'WINDOW', [ ('Clip Editor', 'CLIP_EDITOR', 'WINDOW', []), ('Clip Graph Editor', 'CLIP_EDITOR', 'WINDOW', []), + ('Mask Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image ]), ('View3D Gesture Circle', 'EMPTY', 'WINDOW', []), diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index e4f608e2660..e72778e3776 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -44,11 +44,12 @@ class CLIP_HT_header(Header): sub.menu("CLIP_MT_clip") - if clip: + if clip and sc.mode != 'MASKEDITING': sub.menu("CLIP_MT_track") sub.menu("CLIP_MT_reconstruction") - layout.prop(sc, "view", text="", expand=True) + if sc.mode != 'MASKEDITING': + layout.prop(sc, "view", text="", expand=True) if clip: if sc.view == 'CLIP': @@ -72,6 +73,10 @@ class CLIP_HT_header(Header): row = layout.row() row.template_ID(sc, "clip", open='clip.open') + if sc.mode == 'MASKEDITING': + row = layout.row() + row.template_ID(sc, "mask", new="mask.new") + if clip: tracking = clip.tracking active = tracking.objects.active @@ -545,6 +550,112 @@ class CLIP_PT_tracking_camera(Panel): col.prop(clip.tracking.camera, "k3") +class CLIP_PT_shapes(Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'UI' + bl_label = "Shapes" + + @classmethod + def poll(cls, context): + sc = context.space_data + + return sc.mask and sc.mode == 'MASKEDITING' + + def draw(self, context): + layout = self.layout + + sc = context.space_data + mask = sc.mask + + row = layout.row() + row.template_list(mask, "shapes", + mask, "active_shape_index", rows=3) + + sub = row.column(align=True) + + sub.operator("mask.shape_new", icon='ZOOMIN', text="") + sub.operator("mask.shape_remove", icon='ZOOMOUT', text="") + + active = mask.shapes.active + if active: + layout.prop(active, "name") + + +class CLIP_PT_active_mask_spline(Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'UI' + bl_label = "Active Spline" + + @classmethod + def poll(cls, context): + sc = context.space_data + mask = sc.mask + + if mask and sc.mode == 'MASKEDITING': + return mask.shapes.active and mask.shapes.active.splines.active + + return False + + def draw(self, context): + layout = self.layout + + sc = context.space_data + mask = sc.mask + spline = mask.shapes.active.splines.active + + col = layout.column() + col.prop(spline, "weight_interpolation") + col.prop(spline, "use_cyclic") + + +class CLIP_PT_active_mask_point(Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'UI' + bl_label = "Active Point" + + @classmethod + def poll(cls, context): + sc = context.space_data + mask = sc.mask + + if mask and sc.mode == 'MASKEDITING': + return mask.shapes.active and mask.shapes.active.splines.active_point + + return False + + def draw(self, context): + layout = self.layout + + sc = context.space_data + mask = sc.mask + point = mask.shapes.active.splines.active_point + parent = point.parent + + col = layout.column() + col.prop(point, "handle_type") + + col = layout.column() + col.prop(parent, "use_parent", text="Parent") + if parent.use_parent: + # Currently only parenting yo movie clip is allowed, so do not + # ver-oplicate things for now and use single template_ID + #col.template_any_ID(parent, "id", "id_type", text="") + + col.template_ID(parent, "id") + + if parent.id_type == 'MOVIECLIP' and parent.id: + clip = parent.id + tracking = clip.tracking + + col.prop_search(parent, "parent", tracking, "objects", icon='OBJECT_DATA', text="Object:") + + if parent.parent and parent.parent in tracking.objects: + object = clip.tracking.objects[parent.parent] + col.prop_search(parent, "sub_parent", object, "tracks", icon='ANIM_DATA', text="Track:") + else: + col.prop_search(parent, "sub_parent", clip.tracking, "tracks", icon='ANIM_DATA', text="Track:") + + class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' @@ -595,6 +706,12 @@ class CLIP_PT_marker_display(CLIP_PT_clip_view_panel, Panel): bl_region_type = 'UI' bl_label = "Marker Display" + @classmethod + def poll(cls, context): + sc = context.space_data + + return sc.mode != 'MASKEDITING' + def draw(self, context): layout = self.layout sc = context.space_data diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index cb17a87fd76..dc7e7948088 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -86,6 +86,7 @@ set(SRC_DNA_INC ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_world_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_movieclip_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_tracking_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_mask_types.h ) add_subdirectory(editors) diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index b2bd840a09a..c170cbb5694 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -260,6 +260,7 @@ struct Image *CTX_data_edit_image(const bContext *C); struct Text *CTX_data_edit_text(const bContext *C); struct MovieClip *CTX_data_edit_movieclip(const bContext *C); +struct Mask *CTX_data_edit_mask(const bContext *C); int CTX_data_selected_nodes(const bContext *C, ListBase *list); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index be21996428a..d97e035a547 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -65,7 +65,7 @@ void id_clear_lib_data(struct Main *bmain, struct ID *id); struct ListBase *which_libbase(struct Main *mainlib, short type); -#define MAX_LIBARRAY 40 +#define MAX_LIBARRAY 41 int set_listbasepointers(struct Main *main, struct ListBase **lb); void free_libblock(struct ListBase *lb, void *idv); diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index ffcbb6e40bc..382ce7c1274 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -86,6 +86,7 @@ typedef struct Main { ListBase wm; ListBase gpencil; ListBase movieclip; + ListBase mask; char id_tag_update[256]; } Main; diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h new file mode 100644 index 00000000000..268b7df0247 --- /dev/null +++ b/source/blender/blenkernel/BKE_mask.h @@ -0,0 +1,95 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_MASK_H__ +#define __BKE_MASK_H__ + +struct Main; +struct Mask; +struct MaskParent; +struct MaskShape; +struct MaskSpline; +struct MaskSplinePoint; +struct MaskSplinePointUW; +struct Scene; + +/* shapes */ +struct MaskShape *BKE_mask_shape_new(struct Mask *mask, const char *name); +struct MaskShape *BKE_mask_shape_active(struct Mask *mask); +void BKE_mask_shape_active_set(struct Mask *mask, struct MaskShape *shape); +void BKE_mask_shape_remove(struct Mask *mask, struct MaskShape *shape); + +void BKE_mask_shape_free(struct MaskShape *shape); +void BKE_mask_spline_free(struct MaskSpline *spline); +void BKE_mask_point_free(struct MaskSplinePoint *point); + +void BKE_mask_shape_unique_name(struct Mask *mask, struct MaskShape *shape); + +/* splines */ +struct MaskSpline *BKE_mask_spline_add(struct MaskShape *shape); +int BKE_mask_spline_resolution(struct MaskSpline *spline); +float *BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point); +float *BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, float aspx, + float aspy, int *tot_feather_point); +float *BKE_mask_spline_feather_points(struct MaskSpline *spline, float aspx, float aspy, int *tot_feather_point); + +/* point */ +int BKE_mask_point_has_handle(struct MaskSplinePoint *point); +void BKE_mask_point_handle(struct MaskSplinePoint *point, float aspx, float aspy, float handle[2]); +void BKE_mask_point_set_handle(struct MaskSplinePoint *point, float loc[2], int keep_direction, float aspx, float aspy, float orig_handle[2], float orig_vec[3][3]); +float *BKE_mask_point_segment_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, int *tot_diff_point); +float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, + float aspx, float aspy, int *tot_feather_point); +void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2]); +void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, float aspx, float aspy, float u, float n[2]); +float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *point, float u); +struct MaskSplinePointUW * BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw); +void BKE_mask_point_add_uw(struct MaskSplinePoint *point, float u, float w); + +/* general */ +struct Mask *BKE_mask_new(const char *name); + +void BKE_mask_free(struct Mask *mask); +void BKE_mask_unlink(struct Main *bmain, struct Mask *mask); + +/* parenting */ + +void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime); +void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene); +void BKE_mask_parent_init(struct MaskParent *parent); + +#define MASKPOINT_ISSEL(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT ) +#define MASKPOINT_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } +#define MASKPOINT_DESEL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } +#define MASKPOINT_INVSEL(p) { (p)->bezt.f1 ^= SELECT; (p)->bezt.f2 ^= SELECT; (p)->bezt.f3 ^= SELECT; } + +#define MASKPOINT_CV_ISSEL(p) ( (p)->bezt.f2 & SELECT ) + +#define MASKPOINT_HANDLE_ONLY_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT ) && (((p)->bezt.f2 & SELECT) == 0) ) +#define MASKPOINT_HANDLE_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT ) ) +#define MASKPOINT_HANDLE_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f3 |= SELECT; } + +#endif diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index a4eddd0b590..4f3a6d4e174 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -638,6 +638,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat); #define CMP_NODE_MOVIEDISTORTION 265 #define CMP_NODE_DOUBLEEDGEMASK 266 #define CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED 267 /* DEPRECATED multi file node has been merged into regular CMP_NODE_OUTPUT_FILE */ +#define CMP_NODE_MASK 268 #define CMP_NODE_GLARE 301 #define CMP_NODE_TONEMAP 302 diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index c2a83b5c048..61461044fa7 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -100,6 +100,7 @@ set(SRC intern/lamp.c intern/lattice.c intern/library.c + intern/mask.c intern/material.c intern/mball.c intern/mesh.c @@ -186,6 +187,7 @@ set(SRC BKE_lamp.h BKE_lattice.h BKE_library.h + BKE_mask.h BKE_main.h BKE_material.h BKE_mball.h diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 7a5b4ef9b24..639af36e15f 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -925,6 +925,11 @@ struct MovieClip *CTX_data_edit_movieclip(const bContext *C) return ctx_data_pointer_get(C, "edit_movieclip"); } +struct Mask *CTX_data_edit_mask(const bContext *C) +{ + return ctx_data_pointer_get(C, "edit_mask"); +} + struct EditBone *CTX_data_active_bone(const bContext *C) { return ctx_data_pointer_get(C, "active_bone"); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index d8cdd728c16..95ee3b34644 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2604,6 +2604,18 @@ static void dag_id_flush_update(Scene *sce, ID *id) } } + if (idtype == ID_MSK) { + if (sce->nodetree) { + bNode *node; + + for (node = sce->nodetree->nodes.first; node; node = node->next) { + if (node->id == id) { + nodeUpdate(sce->nodetree, node); + } + } + } + } + /* camera's matrix is used to orient reconstructed stuff, * so it should happen tracking-related constraints recalculation * when camera is changing (sergey) */ diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index cd246681f3c..1f4d9d01fe1 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -79,6 +79,7 @@ static IDType idtypes[]= { { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE}, { ID_WM, "WindowManager", "window_managers", 0}, { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE}, + { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE}, }; static int nidtypes= sizeof(idtypes)/sizeof(idtypes[0]); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 2924ea457a8..bd147db34d7 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -66,6 +66,7 @@ #include "DNA_world_types.h" #include "DNA_gpencil_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" @@ -108,6 +109,7 @@ #include "BKE_speaker.h" #include "BKE_utildefines.h" #include "BKE_movieclip.h" +#include "BKE_mask.h" #include "RNA_access.h" @@ -486,6 +488,8 @@ ListBase *which_libbase(Main *mainlib, short type) return &(mainlib->gpencil); case ID_MC: return &(mainlib->movieclip); + case ID_MSK: + return &(mainlib->mask); } return NULL; } @@ -569,6 +573,7 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a++]= &(main->library); lb[a++]= &(main->wm); lb[a++]= &(main->movieclip); + lb[a++]= &(main->mask); lb[a]= NULL; @@ -680,6 +685,9 @@ static ID *alloc_libblock_notest(short type) case ID_MC: id = MEM_callocN(sizeof(MovieClip), "Movie Clip"); break; + case ID_MSK: + id = MEM_callocN(sizeof(Mask), "Mask"); + break; } return id; } @@ -888,6 +896,9 @@ void free_libblock(ListBase *lb, void *idv) case ID_MC: BKE_movieclip_free((MovieClip *)id); break; + case ID_MSK: + BKE_mask_free((Mask *)id); + break; } if (id->properties) { diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c new file mode 100644 index 00000000000..ad0baa9d63c --- /dev/null +++ b/source/blender/blenkernel/intern/mask.c @@ -0,0 +1,890 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/mask.c + * \ingroup bke + */ + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "DNA_mask_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_movieclip_types.h" +#include "DNA_tracking_types.h" + +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_mask.h" +#include "BKE_tracking.h" +#include "BKE_utildefines.h" + +/* shapes */ + +MaskShape *BKE_mask_shape_new(Mask *mask, const char *name) +{ + MaskShape *shape = MEM_callocN(sizeof(MaskShape), "new mask shape"); + + if (name && name[0]) + BLI_strncpy(shape->name, name, sizeof(shape->name)); + else + strcpy(shape->name, "Shape"); + + BLI_addtail(&mask->shapes, shape); + + BKE_mask_shape_unique_name(mask, shape); + + mask->tot_shape++; + + return shape; +} + +MaskShape *BKE_mask_shape_active(Mask *mask) +{ + return BLI_findlink(&mask->shapes, mask->shapenr); +} + +void BKE_mask_shape_active_set(Mask *mask, MaskShape *shape) +{ + int index = BLI_findindex(&mask->shapes, shape); + + if (index >= 0) + mask->shapenr = index; + else + mask->shapenr = 0; +} + +void BKE_mask_shape_remove(Mask *mask, MaskShape *shape) +{ + BLI_remlink(&mask->shapes, shape); + BKE_mask_shape_free(shape); + + mask->tot_shape--; + + if (mask->shapenr >= mask->tot_shape) + mask->shapenr = mask->tot_shape - 1; +} + +void BKE_mask_shape_unique_name(Mask *mask, MaskShape *shape) +{ + BLI_uniquename(&mask->shapes, shape, "Shape", '.', offsetof(MaskShape, name), sizeof(shape->name)); +} + +/* splines */ + +MaskSpline *BKE_mask_spline_add(MaskShape *shape) +{ + MaskSpline *spline; + + spline = MEM_callocN(sizeof(MaskSpline), "new shape spline"); + BLI_addtail(&shape->splines, spline); + + /* spline shall have one point at least */ + spline->points = MEM_callocN(sizeof(MaskSplinePoint), "new shape spline point"); + spline->tot_point = 1; + + /* cyclic shapes are more usually used */ + spline->flag |= MASK_SPLINE_CYCLIC; + + spline->weight_interp = MASK_SPLINE_INTERP_LINEAR; + + BKE_mask_parent_init(&spline->parent); + + return spline; +} + +int BKE_mask_spline_resolution(MaskSpline *spline) +{ + const float max_segment = 0.01; + int i, resol = 1; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *next_point; + BezTriple *bezt, *next_bezt; + float a, b, c, len; + int cur_resol; + + if (i == spline->tot_point - 1) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next_point = &spline->points[0]; + else + break; + } + else + next_point = &spline->points[i + 1]; + + bezt = &point->bezt; + next_bezt = &next_point->bezt; + + a = len_v3v3(bezt->vec[1], bezt->vec[2]); + b = len_v3v3(bezt->vec[2], next_bezt->vec[0]); + c = len_v3v3(next_bezt->vec[0], next_bezt->vec[1]); + + len = a + b + c; + cur_resol = len / max_segment; + + resol = MAX2(resol, cur_resol); + } + + return resol; +} + +int BKE_mask_spline_feather_resolution(MaskSpline *spline) +{ + const float max_segment = 0.005; + int resol = BKE_mask_spline_resolution(spline); + float max_jump = 0.0f; + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + float prev_u, prev_w; + int j; + + prev_u = 0.0f; + prev_w = point->bezt.weight; + + for (j = 0; j < point->tot_uw; j++) { + float jump = fabsf((point->uw[j].w - prev_w) / (point->uw[j].u - prev_u)); + + max_jump = MAX2(max_jump, jump); + + prev_u = point->uw[j].u; + prev_w = point->uw[j].w; + } + } + + resol += max_jump / max_segment; + + return resol; +} + +float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) +{ + MaskSplinePoint *point, *prev; + float *diff_points, *fp; + int a, len, resol = BKE_mask_spline_resolution(spline); + + if (spline->tot_point <= 1) { + /* nothing to differentiate */ + *tot_diff_point = 0; + return NULL; + } + + /* count */ + len = (spline->tot_point - 1) * resol; + + if (spline->flag & MASK_SPLINE_CYCLIC) + len += resol; + else + len++; + + /* len+1 because of 'forward_diff_bezier' function */ + *tot_diff_point = len; + diff_points = fp = MEM_callocN((len + 1)*2*sizeof(float), "mask spline vets"); + + a = spline->tot_point - 1; + if (spline->flag & MASK_SPLINE_CYCLIC) + a++; + + prev = spline->points; + point = prev + 1; + + while (a--) { + BezTriple *prevbezt; + BezTriple *bezt; + int j; + + if (a==0 && (spline->flag & MASK_SPLINE_CYCLIC)) + point = spline->points; + + prevbezt = &prev->bezt; + bezt = &point->bezt; + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], prevbezt->vec[2][j], + bezt->vec[0][j], bezt->vec[1][j], + fp + j, resol, 2 * sizeof(float)); + } + + fp += 2 * resol; + + if (a==0 && (spline->flag & MASK_SPLINE_CYCLIC)==0) { + copy_v2_v2(fp, bezt->vec[1]); + } + + prev = point; + point++; + } + + return diff_points; +} + +float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, float aspx, float aspy, + int *tot_feather_point) +{ + float *feather, *fp; + int i, j, tot, resol = BKE_mask_spline_feather_resolution(spline); + + tot = resol * spline->tot_point; + feather = fp = MEM_callocN(2 * tot * sizeof(float), "mask spline feather diff points"); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + for (j = 0; j < resol; j++, fp += 2) { + float u = (float) j / resol, weight; + float co[2], n[2]; + + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, aspx, aspy, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + fp[0] = co[0] + n[0] * weight; + fp[1] = co[1] + n[1] * weight; + } + } + + *tot_feather_point = tot; + + return feather; +} + +float *BKE_mask_spline_feather_points(MaskSpline *spline, float aspx, float aspy, int *tot_feather_point) +{ + int i, tot = 0; + float *feather, *fp; + + /* count */ + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + tot += point->tot_uw + 1; + } + + /* create data */ + feather = fp = MEM_callocN(2 * tot * sizeof(float), "mask spline feather points"); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + BezTriple *bezt = &point->bezt; + float weight, n[2]; + int j; + + BKE_mask_point_normal(spline, point, aspx, aspy, 0.0f, n); + weight = BKE_mask_point_weight(spline, point, 0.0f); + + fp[0] = bezt->vec[1][0] + n[0] * weight; + fp[1] = bezt->vec[1][1] + n[1] * weight; + fp += 2; + + for (j = 0; j < point->tot_uw; j++) { + float u = point->uw[j].u; + float co[2]; + + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, aspx, aspy, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + fp[0] = co[0] + n[0] * weight; + fp[1] = co[1] + n[1] * weight; + + fp += 2; + } + } + + *tot_feather_point = tot; + + return feather; +} + +/* point */ + +int BKE_mask_point_has_handle(MaskSplinePoint *point) +{ + BezTriple *bezt = &point->bezt; + + return bezt->h1 == HD_ALIGN; +} + +void BKE_mask_point_handle(MaskSplinePoint *point, float aspx, float aspy, float handle[2]) +{ + float vec[2]; + + sub_v2_v2v2(vec, point->bezt.vec[0], point->bezt.vec[1]); + + vec[0] *= aspx; + vec[1] *= aspy; + + handle[0] = (point->bezt.vec[1][0]*aspx + vec[1]) / aspx; + handle[1] = (point->bezt.vec[1][1]*aspy - vec[0]) / aspy; +} + +void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_direction, float aspx, float aspy, + float orig_handle[2], float orig_vec[3][3]) +{ + BezTriple *bezt = &point->bezt; + float v1[2], v2[2], vec[2]; + + if (keep_direction) { + sub_v2_v2v2(v1, loc, orig_vec[1]); + sub_v2_v2v2(v2, orig_handle, orig_vec[1]); + + v1[0] *= aspx; + v1[1] *= aspy; + v2[0] *= aspx; + v2[1] *= aspx; + + project_v2_v2v2(vec, v1, v2); + + if (dot_v2v2(v2, vec) > 0) { + float len = len_v2(vec); + + sub_v2_v2v2(v1, orig_vec[0], orig_vec[1]); + + v1[0] *= aspx; + v1[1] *= aspy; + + mul_v2_fl(v1, len / len_v2(v1)); + + v1[0] /= aspx; + v1[1] /= aspy; + + add_v2_v2v2(bezt->vec[0], bezt->vec[1], v1); + sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v1); + } + else { + copy_v3_v3(bezt->vec[0], bezt->vec[1]); + copy_v3_v3(bezt->vec[2], bezt->vec[1]); + } + } else { + sub_v2_v2v2(v1, loc, bezt->vec[1]); + + v2[0] = -v1[1] * aspy / aspx; + v2[1] = v1[0] * aspx / aspy; + + add_v2_v2v2(bezt->vec[0], bezt->vec[1], v2); + sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v2); + } +} + +float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, float aspx, float aspy, + int *tot_feather_point) +{ + float *feather, *fp; + int i, resol = BKE_mask_spline_feather_resolution(spline); + + feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); + + for (i = 0; i < resol; i++, fp += 2) { + float u = (float)(i % resol) / resol, weight; + float co[2], n[2]; + + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, aspx, aspy, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + fp[0] = co[0] + n[0] * weight; + fp[1] = co[1] + n[1] * weight; + } + + *tot_feather_point = resol; + + return feather; +} + +float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_diff_point) +{ + BezTriple *bezt, *next; + float *diff_points, *fp; + int j, resol = BKE_mask_spline_resolution(spline); + + bezt = &point->bezt; + + if (point == &spline->points[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next = &(spline->points[0].bezt); + else + next = NULL; + } + else next = &((point + 1))->bezt; + + if (!next) + return NULL; + + /* resol+1 because of 'forward_diff_bezier' function */ + *tot_diff_point = resol + 1; + diff_points = fp = MEM_callocN((resol + 1)*2*sizeof(float), "mask segment vets"); + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j], + next->vec[0][j], next->vec[1][j], + fp + j, resol, 2 * sizeof(float)); + } + + copy_v2_v2(fp + 2 * resol, next->vec[1]); + + return diff_points; +} + +void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float u, float co[2]) +{ + BezTriple *bezt = &point->bezt, *next; + float q0[2], q1[2], q2[2], r0[2], r1[2]; + + if (point == &spline->points[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next = &(spline->points[0].bezt); + else + next = NULL; + } + else next = &((point + 1))->bezt; + + if (!next) { + copy_v2_v2(co, bezt->vec[1]); + return; + } + + interp_v2_v2v2(q0, bezt->vec[1], bezt->vec[2], u); + interp_v2_v2v2(q1, bezt->vec[2], next->vec[0], u); + interp_v2_v2v2(q2, next->vec[0], next->vec[1], u); + + interp_v2_v2v2(r0, q0, q1, u); + interp_v2_v2v2(r1, q1, q2, u); + + interp_v2_v2v2(co, r0, r1, u); +} + +void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float aspx, float aspy, float u, float n[2]) +{ + BezTriple *bezt = &point->bezt, *next; + float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2]; + + if (point == &spline->points[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next = &(spline->points[0].bezt); + else + next = NULL; + } + else next = &((point + 1))->bezt; + + if (!next) { + BKE_mask_point_handle(point, aspx, aspy, vec); + + sub_v2_v2v2(n, vec, bezt->vec[1]); + + n[0] *= aspx; + n[1] *= aspy; + + normalize_v2(n); + + n[0] /= aspx; + n[1] /= aspy; + + return; + } + + interp_v2_v2v2(q0, bezt->vec[1], bezt->vec[2], u); + interp_v2_v2v2(q1, bezt->vec[2], next->vec[0], u); + interp_v2_v2v2(q2, next->vec[0], next->vec[1], u); + + interp_v2_v2v2(r0, q0, q1, u); + interp_v2_v2v2(r1, q1, q2, u); + + sub_v2_v2v2(vec, r1, r0); + + n[0] = -vec[1] * aspy; + n[1] = vec[0] * aspx; + + normalize_v2(n); + + n[0] /= aspx; + n[1] /= aspy; +} + +float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) +{ + BezTriple *bezt = &point->bezt, *next; + float cur_u, cur_w, next_u, next_w, fac; + int i; + + if (point == &spline->points[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next = &(spline->points[0].bezt); + else + next = NULL; + } + else next = &((point + 1))->bezt; + + if (!next) + return bezt->weight; + + for (i = 0; i < point->tot_uw + 1; i++) { + + if (i == 0) { + cur_u = 0.0f; + cur_w = bezt->weight; + } + else { + cur_u = point->uw[i - 1].u; + cur_w = point->uw[i - 1].w; + } + + if (i == point->tot_uw) { + next_u = 1.0f; + next_w = next->weight; + } + else { + next_u = point->uw[i].u; + next_w = point->uw[i].w; + } + + if (u >= cur_u && u <= next_u) { + break; + } + } + + fac = (u - cur_u) / (next_u - cur_u); + + if (spline->weight_interp == MASK_SPLINE_INTERP_EASE) + return cur_w + (next_w - cur_w) * (3.0f * fac * fac - 2.0f * fac * fac * fac); + else + return (1.0f - fac) * cur_w + fac * next_w; +} + +MaskSplinePointUW *BKE_mask_point_sort_uw(MaskSplinePoint *point, MaskSplinePointUW *uw) +{ + if (point->tot_uw > 1) { + int idx = uw - point->uw; + + if (idx > 0 && point->uw[idx - 1].u > uw->u) { + while (idx > 0 && point->uw[idx - 1].u > point->uw[idx].u) { + SWAP(MaskSplinePointUW, point->uw[idx - 1], point->uw[idx]); + idx--; + } + } + + if (idx < point->tot_uw - 1 && point->uw[idx + 1].u < uw->u) { + while (idx < point->tot_uw - 1 && point->uw[idx + 1].u < point->uw[idx].u) { + SWAP(MaskSplinePointUW, point->uw[idx + 1], point->uw[idx]); + idx++; + } + } + + return &point->uw[idx]; + } + + return uw; +} + +void BKE_mask_point_add_uw(MaskSplinePoint *point, float u, float w) +{ + if (!point->uw) + point->uw = MEM_callocN(sizeof(*point->uw), "mask point uw"); + else + point->uw = MEM_reallocN(point->uw, (point->tot_uw + 1) * sizeof(*point->uw)); + + point->uw[point->tot_uw].u = u; + point->uw[point->tot_uw].w = w; + + point->tot_uw++; + + BKE_mask_point_sort_uw(point, &point->uw[point->tot_uw - 1]); +} + +/* only mask block itself */ +static Mask *mask_alloc(const char *name) +{ + Mask *mask; + + mask = alloc_libblock(&G.main->mask, ID_MSK, name); + + return mask; +} + +Mask *BKE_mask_new(const char *name) +{ + Mask *mask; + char mask_name[MAX_ID_NAME - 2]; + + if (name && name[0]) + BLI_strncpy(mask_name, name, sizeof(mask_name)); + else + strcpy(mask_name, "Mask"); + + mask = mask_alloc(mask_name); + + return mask; +} + +void BKE_mask_point_free(MaskSplinePoint *point) +{ + if (point->uw) + MEM_freeN(point->uw); +} + +void BKE_mask_spline_free(MaskSpline *spline) +{ + int i = 0; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + BKE_mask_point_free(point); + } + + MEM_freeN(spline->points); + + MEM_freeN(spline); +} + +void BKE_mask_shape_free(MaskShape *shape) +{ + MaskSpline *spline = shape->splines.first; + + while (spline) { + MaskSpline *next_spline = spline->next; + + BLI_remlink(&shape->splines, spline); + BKE_mask_spline_free(spline); + + spline = next_spline; + } + + MEM_freeN(shape); +} + +void BKE_mask_free(Mask *mask) +{ + MaskShape *shape = mask->shapes.first; + + while (shape) { + MaskShape *next_shape = shape->next; + + BLI_remlink(&mask->shapes, shape); + BKE_mask_shape_free(shape); + + shape = next_shape; + } +} + +void BKE_mask_unlink(Main *bmain, Mask *mask) +{ + bScreen *scr; + ScrArea *area; + SpaceLink *sl; + + for (scr = bmain->screen.first; scr; scr = scr->id.next) { + for (area = scr->areabase.first; area; area = area->next) { + for(sl = area->spacedata.first; sl; sl = sl->next) { + if(sl->spacetype == SPACE_CLIP) { + SpaceClip *sc = (SpaceClip *) sl; + + if(sc->mask == mask) + sc->mask = NULL; + } + } + } + } + + mask->id.us= 0; +} + +static void evaluate_mask_parent(MaskParent *parent, float ctime, float co[2]) +{ + if (!parent) + return; + + if ((parent->flag & MASK_PARENT_ACTIVE) == 0) + return; + + if (parent->id_type == ID_MC) { + if (parent->id) { + MovieClip *clip = (MovieClip *) parent->id; + MovieTracking *tracking = (MovieTracking *) &clip->tracking; + MovieTrackingObject *ob = BKE_tracking_named_object(tracking, parent->parent); + + if (ob) { + MovieTrackingTrack *track = BKE_tracking_named_track(tracking, ob, parent->sub_parent); + + if (track) { + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, ctime); + + copy_v2_v2(co, marker->pos); + } + } + } + } +} + +static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev_point, MaskSplinePoint *next_point) +{ + BezTriple *bezt = &point->bezt; + BezTriple *prev_bezt = NULL, *next_bezt = NULL; + int handle_type = bezt->h1; + + if (prev_point) + prev_bezt = &prev_point->bezt; + + if (next_point) + next_bezt = &next_point->bezt; + + if (handle_type == HD_VECT) { + BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + } + else if (handle_type == HD_AUTO) { + BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + } + else if (handle_type == HD_ALIGN) { + float v1[3], v2[3]; + float vec[3], h[3]; + + sub_v3_v3v3(v1, bezt->vec[0], bezt->vec[1]); + sub_v3_v3v3(v2, bezt->vec[2], bezt->vec[1]); + add_v3_v3v3(vec, v1, v2); + + if (len_v3(vec) > 1e-3) { + h[0] = vec[1]; + h[1] = -vec[0]; + h[2] = 0.0f; + } + else { + copy_v3_v3(h, v1); + } + + add_v3_v3v3(bezt->vec[0], bezt->vec[1], h); + sub_v3_v3v3(bezt->vec[2], bezt->vec[1], h); + } +} + +void BKE_mask_calc_handles(Mask *mask) +{ + MaskShape *shape = mask->shapes.first; + + while (shape) { + MaskSpline *spline = shape->splines.first; + int i; + + while (spline) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *prev_point, *next_point; + + if (i == 0) { + if (spline->flag & MASK_SPLINE_CYCLIC) + prev_point = &spline->points[spline->tot_point - 1]; + else + prev_point = NULL; + } + else prev_point = point - 1; + + if (i == spline->tot_point - 1) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next_point = &spline->points[0]; + else + next_point = NULL; + } + else next_point = point + 1; + + mask_calc_point_handle(point, prev_point, next_point); + } + + spline = spline->next; + } + + shape = shape->next; + } +} + +void BKE_mask_evaluate(Mask *mask, float ctime) +{ + MaskShape *shape = mask->shapes.first; + + while (shape) { + MaskSpline *spline = shape->splines.first; + int i; + + while (spline) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + BezTriple *bezt = &point->bezt; + float co[2], delta[2]; + + copy_v2_v2(co, bezt->vec[1]); + evaluate_mask_parent(&point->parent, ctime, co); + sub_v2_v2v2(delta, co, bezt->vec[1]); + + add_v2_v2(bezt->vec[0], delta); + add_v2_v2(bezt->vec[1], delta); + add_v2_v2(bezt->vec[2], delta); + } + + spline = spline->next; + } + + shape = shape->next; + } + + BKE_mask_calc_handles(mask); +} + +void BKE_mask_evaluate_all_masks(Main *bmain, float ctime) +{ + Mask *mask; + + for (mask = bmain->mask.first; mask; mask = mask->id.next) { + BKE_mask_evaluate(mask, ctime); + } +} + +void BKE_mask_update_scene(Main *bmain, Scene *scene) +{ + Mask *mask; + + for (mask = bmain->mask.first; mask; mask = mask->id.next) { + if (mask->id.flag & LIB_ID_RECALC) { + BKE_mask_evaluate_all_masks(bmain, CFRA); + } + } +} + +void BKE_mask_parent_init(MaskParent *parent) +{ + parent->id_type = ID_MC; +} diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index b2a85ad0629..19713f60ec8 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1930,6 +1930,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_transform(ttype); register_node_type_cmp_stabilize2d(ttype); register_node_type_cmp_moviedistortion(ttype); + register_node_type_cmp_mask(ttype); } static void registerShaderNodes(bNodeTreeType *ttype) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 864260833a6..2a311a871f0 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -63,6 +63,7 @@ #include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_mask.h" #include "BKE_node.h" #include "BKE_object.h" #include "BKE_paint.h" @@ -1003,6 +1004,9 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen /* update sound system animation */ sound_update_scene(scene); + + /* update masking curves */ + BKE_mask_update_scene(bmain, scene); } /* this is called in main loop, doing tagged updates before redraw */ @@ -1073,6 +1077,8 @@ void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) * so don't call within 'scene_update_tagged_recursive' */ DAG_scene_update_flags(bmain, sce, lay, TRUE); // only stuff that moves or needs display still + BKE_mask_evaluate_all_masks(bmain, ctime); + /* All 'standard' (i.e. without any dependencies) animation is handled here, * with an 'local' to 'macro' order of evaluation. This should ensure that * settings stored nestled within a hierarchy (i.e. settings in a Texture block diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 993426545ee..753cd93b89a 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -94,6 +94,7 @@ #include "DNA_vfont_types.h" #include "DNA_world_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "MEM_guardedalloc.h" @@ -5387,6 +5388,7 @@ static void lib_link_screen(FileData *fd, Main *main) SpaceClip *sclip= (SpaceClip *)sl; sclip->clip= newlibadr_us(fd, sc->id.lib, sclip->clip); + sclip->mask= newlibadr_us(fd, sc->id.lib, sclip->mask); sclip->scopes.track_preview = NULL; sclip->draw_context = NULL; @@ -5654,6 +5656,7 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene) SpaceClip *sclip= (SpaceClip *)sl; sclip->clip= restore_pointer_by_name(newmain, (ID *)sclip->clip, 1); + sclip->mask= restore_pointer_by_name(newmain, (ID *)sclip->mask, 1); sclip->scopes.ok = 0; } @@ -6238,6 +6241,90 @@ static void lib_link_movieclip(FileData *fd, Main *main) } } +/* ***************** READ MOVIECLIP *************** */ + +static void direct_link_mask(FileData *fd, Mask *mask) +{ + MaskShape *shape; + + mask->adt = newdataadr(fd, mask->adt); + + link_list(fd, &mask->shapes); + + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline; + + link_list(fd, &shape->splines); + + spline = shape->splines.first; + while (spline) { + int i; + + spline->points = newdataadr(fd, spline->points); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (point->tot_uw) + point->uw = newdataadr(fd, point->uw); + } + + spline = spline->next; + } + + shape->act_spline = newdataadr(fd, shape->act_spline); + shape->act_point = newdataadr(fd, shape->act_point); + + shape = shape->next; + } +} + +static void lib_link_mask_parent(FileData *fd, Mask *mask, MaskParent *parent) +{ + parent->id = newlibadr_us(fd, mask->id.lib, parent->id); +} + +static void lib_link_mask(FileData *fd, Main *main) +{ + Mask *mask; + + mask = main->mask.first; + while (mask) { + if(mask->id.flag & LIB_NEEDLINK) { + MaskShape *shape; + + if (mask->adt) + lib_link_animdata(fd, &mask->id, mask->adt); + + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline; + + spline = shape->splines.first; + while (spline) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + lib_link_mask_parent(fd, mask, &point->parent); + } + + lib_link_mask_parent(fd, mask, &spline->parent); + + spline = spline->next; + } + + shape = shape->next; + } + + mask->id.flag -= LIB_NEEDLINK; + } + mask = mask->id.next; + } +} + /* ************** GENERAL & MAIN ******************** */ @@ -6444,6 +6531,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID case ID_MC: direct_link_movieclip(fd, (MovieClip *)id); break; + case ID_MSK: + direct_link_mask(fd, (Mask *)id); + break; } /*link direct data of ID properties*/ @@ -13344,6 +13434,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_brush(fd, main); lib_link_particlesettings(fd, main); lib_link_movieclip(fd, main); + lib_link_mask(fd, main); lib_link_mesh(fd, main); /* as last: tpage images with users at zero */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 5580c9efc9b..e11e0274b28 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -133,6 +133,7 @@ Any case: direct data is ALWAYS after the lib block #include "DNA_world_types.h" #include "DNA_windowmanager_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "MEM_guardedalloc.h" // MEM_freeN #include "BLI_bitmap.h" @@ -2732,6 +2733,54 @@ static void write_movieclips(WriteData *wd, ListBase *idbase) mywrite(wd, MYWRITE_FLUSH, 0); } +static void write_masks(WriteData *wd, ListBase *idbase) +{ + Mask *mask; + + mask = idbase->first; + while (mask) { + if (mask->id.us > 0 || wd->current) { + MaskShape *shape; + + writestruct(wd, ID_MSK, "Mask", 1, mask); + + if (mask->adt) + write_animdata(wd, mask->adt); + + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline; + + writestruct(wd, DATA, "MaskShape", 1, shape); + + spline = shape->splines.first; + while (spline) { + int i; + + writestruct(wd, DATA, "MaskSpline", 1, spline); + writestruct(wd, DATA, "MaskSplinePoint", spline->tot_point, spline->points); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (point->tot_uw) + writestruct(wd, DATA, "MaskSplinePointUW", point->tot_uw, point->uw); + } + + spline = spline->next; + } + + shape = shape->next; + } + } + + mask = mask->id.next; + } + + /* flush helps the compression for undo-save */ + mywrite(wd, MYWRITE_FLUSH, 0); +} + /* context is usually defined by WM, two cases where no WM is available: * - for forward compatibility, curscreen has to be saved * - for undofile, curscene needs to be saved */ @@ -2816,6 +2865,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil write_screens (wd, &mainvar->screen); } write_movieclips (wd, &mainvar->movieclip); + write_masks (wd, &mainvar->mask); write_scenes (wd, &mainvar->scene); write_curves (wd, &mainvar->curve); write_mballs (wd, &mainvar->mball); diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 088376b20ef..67ed77bcc4b 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -24,6 +24,7 @@ if(WITH_BLENDER) add_subdirectory(curve) add_subdirectory(gpencil) add_subdirectory(interface) + add_subdirectory(mask) add_subdirectory(mesh) add_subdirectory(metaball) add_subdirectory(object) diff --git a/source/blender/editors/SConscript b/source/blender/editors/SConscript index ed66a76a324..d08b496f0ef 100644 --- a/source/blender/editors/SConscript +++ b/source/blender/editors/SConscript @@ -8,6 +8,7 @@ SConscript(['datafiles/SConscript', 'interface/SConscript', 'animation/SConscript', 'armature/SConscript', + 'mask/SConscript', 'mesh/SConscript', 'metaball/SConscript', 'object/SConscript', diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index db6d9bbd013..285f1487a71 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -36,6 +36,7 @@ struct bContext; struct bScreen; struct ImBuf; struct Main; +struct Mask; struct MovieClip; struct SpaceClip; struct wmEvent; @@ -45,13 +46,19 @@ int ED_space_clip_poll(struct bContext *C); int ED_space_clip_tracking_poll(struct bContext *C); int ED_space_clip_tracking_size_poll(struct bContext *C); int ED_space_clip_tracking_frame_poll(struct bContext *C); +int ED_space_clip_maskediting_poll(struct bContext *C); +int ED_space_clip_maskediting_mask_poll(bContext *C); void ED_space_clip_set(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip); struct MovieClip *ED_space_clip(struct SpaceClip *sc); +struct Mask *ED_space_clip_mask(struct SpaceClip *sc); void ED_space_clip_size(struct SpaceClip *sc, int *width, int *height); void ED_space_clip_zoom(struct SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy); void ED_space_clip_aspect(struct SpaceClip *sc, float *aspx, float *aspy); +void ED_space_clip_mask_size(struct SpaceClip *sc, int *width, int *height); +void ED_space_clip_mask_aspect(struct SpaceClip *sc, float *aspx, float *aspy); + struct ImBuf *ED_space_clip_get_buffer(struct SpaceClip *sc); struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc, float loc[2], float *scale, float *angle); @@ -68,6 +75,8 @@ void ED_space_clip_unload_movieclip_buffer(struct SpaceClip *sc); void ED_space_clip_free_texture_buffer(struct SpaceClip *sc); int ED_space_clip_show_trackedit(struct SpaceClip *sc); +int ED_space_clip_show_maskedit(struct SpaceClip *sc); +void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask); void ED_space_clip_update_dopesheet(struct SpaceClip *sc); diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h new file mode 100644 index 00000000000..5df91b4032a --- /dev/null +++ b/source/blender/editors/include/ED_mask.h @@ -0,0 +1,44 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ED_mask.h + * \ingroup editors + */ + +#ifndef __ED_MASK_H__ +#define __ED_MASK_H__ + +struct wmKeyConfig; + +/* mask_editor.c */ +void ED_operatortypes_mask(void); +void ED_keymap_mask(struct wmKeyConfig *keyconf); +void ED_operatormacros_mask(void); + +/* mask_draw.c */ +void ED_mask_draw(bContext *C, int width, int height, float zoomx, float zoomy); + +#endif /* ED_TEXT_H */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index f62befdaa31..44a66d436db 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -169,6 +169,7 @@ int ED_operator_editmball(struct bContext *C); int ED_operator_uvedit(struct bContext *C); int ED_operator_uvmap(struct bContext *C); int ED_operator_posemode(struct bContext *C); +int ED_operator_mask(struct bContext *C); /* default keymaps, bitflags */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index f6dee351c29..2d6379ad8a6 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -95,6 +95,7 @@ enum { #define CTX_BMESH 64 #define CTX_NDOF 128 #define CTX_MOVIECLIP 256 +#define CTX_MASK 512 /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index bafd85e9451..c6bc975d981 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -576,8 +576,10 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co row = uiLayoutRow(layout, 1); /* Label - either use the provided text, or will become "ID-Block:" */ - if (text) - uiItemL(row, text, ICON_NONE); + if (text) { + if (text[0]) + uiItemL(row, text, ICON_NONE); + } else uiItemL(row, "ID-Block:", ICON_NONE); diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt new file mode 100644 index 00000000000..fc1d2f4be6b --- /dev/null +++ b/source/blender/editors/mask/CMakeLists.txt @@ -0,0 +1,47 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012 Blender Foundation. +# +# Contributor(s): Blender Foundation, +# Sergey Sharybin +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + ../include + ../../blenkernel + ../../blenloader + ../../blenlib + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/guardedalloc + ${GLEW_INCLUDE_PATH} +) + +set(INC_SYS +) + +set(SRC + mask_draw.c + mask_editor.c + mask_ops.c + + mask_intern.h +) + +blender_add_lib(bf_editor_mask "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/mask/SConscript b/source/blender/editors/mask/SConscript new file mode 100644 index 00000000000..4af000d038d --- /dev/null +++ b/source/blender/editors/mask/SConscript @@ -0,0 +1,9 @@ +#!/usr/bin/python +Import ('env') + +sources = env.Glob('*.c') +defs = [] +incs = '../include ../../blenkernel ../../blenloader ../../blenlib ../../windowmanager ../../makesdna' +incs += ' ../../makesrna #/extern/glew/include #/intern/guardedalloc' + +env.BlenderLib ( 'bf_editors_mask', sources, Split(incs), defs, libtype=['core'], priority=[100] ) diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c new file mode 100644 index 00000000000..d898a1c5232 --- /dev/null +++ b/source/blender/editors/mask/mask_draw.c @@ -0,0 +1,270 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_draw.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_mask.h" + +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "ED_mask.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "UI_resources.h" + +#include "mask_intern.h" // own include + +typedef struct PixelSpaceContext { + int width, height; + float zoomx, zoomy; + float aspx, aspy; +} PixelSpaceContext; + +static void set_spline_color(MaskShape *shape, MaskSpline *spline) +{ + if (spline->flag & SELECT) { + if (shape->act_spline == spline) + glColor3f(1.0f, 1.0f, 1.0f); + else + glColor3f(1.0f, 0.0f, 0.0f); + } + else { + glColor3f(0.5f, 0.0f, 0.0f); + } +} + +/* return non-zero if spline is selected */ +static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceContext *pixelspace) +{ + int i, hsize, tot_feather_point; + float *feather_points, *fp; + + if (!spline->tot_point) + return; + + hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); + + glPointSize(hsize); + + /* feather points */ + feather_points = fp = BKE_mask_spline_feather_points(spline, pixelspace->aspx, pixelspace->aspy, &tot_feather_point); + for (i = 0; i < spline->tot_point; i++) { + int j; + MaskSplinePoint *point = &spline->points[i]; + + for (j = 0; j < point->tot_uw + 1; j++) { + int sel = FALSE; + + if (j == 0) { + sel = MASKPOINT_ISSEL(point); + } + else { + sel = point->uw[j - 1].flag & SELECT; + } + + if (sel) { + if (point == shape->act_point) + glColor3f(1.0f, 1.0f, 1.0f); + else + glColor3f(1.0f, 1.0f, 0.0f); + } else + glColor3f(0.5f, 0.5f, 0.0f); + + glBegin(GL_POINTS); + glVertex2fv(fp); + glEnd(); + + fp += 2; + } + } + MEM_freeN(feather_points); + + /* control points */ + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + BezTriple *bezt = &point->bezt; + float vert[2], handle[2]; + int has_handle = BKE_mask_point_has_handle(point);; + + copy_v2_v2(vert, bezt->vec[1]); + BKE_mask_point_handle(point, pixelspace->aspx, pixelspace->aspy, handle); + + /* draw handle segment */ + if (has_handle) { + set_spline_color(shape, spline); + + glBegin(GL_LINES); + glVertex3fv(vert); + glVertex3fv(handle); + glEnd(); + } + + /* draw CV point */ + if (MASKPOINT_CV_ISSEL(point)) { + if (point == shape->act_point) + glColor3f(1.0f, 1.0f, 1.0f); + else + glColor3f(1.0f, 1.0f, 0.0f); + } else + glColor3f(0.5f, 0.5f, 0.0f); + + glBegin(GL_POINTS); + glVertex3fv(vert); + glEnd(); + + /* draw handle points */ + if (has_handle) { + if (MASKPOINT_HANDLE_ISSEL(point)) { + if (point == shape->act_point) + glColor3f(1.0f, 1.0f, 1.0f); + else + glColor3f(1.0f, 1.0f, 0.0f); + } else + glColor3f(0.5f, 0.5f, 0.0f); + + glBegin(GL_POINTS); + glVertex3fv(handle); + glEnd(); + } + } + + glPointSize(1.0f); +} + +static void draw_spline_curve_lines(float *points, int tot_point, int closed) +{ + int i; + float *fp = points; + + if (closed) + glBegin(GL_LINE_LOOP); + else + glBegin(GL_LINE_STRIP); + + for (i = 0; i < tot_point; i++, fp+=2) { + glVertex3fv(fp); + } + glEnd(); +} + +static void draw_dashed_curve(MaskSpline *spline, float *points, int tot_point) +{ + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_OR); + + draw_spline_curve_lines(points, tot_point, spline->flag & MASK_SPLINE_CYCLIC); + + glDisable(GL_COLOR_LOGIC_OP); + glLineStipple(3, 0xaaaa); + glEnable(GL_LINE_STIPPLE); + + glColor3f(0.0f, 0.0f, 0.0f); + draw_spline_curve_lines(points, tot_point, spline->flag & MASK_SPLINE_CYCLIC); + + glDisable(GL_LINE_STIPPLE); +} + +static void draw_spline_curve(MaskShape *shape, MaskSpline *spline, PixelSpaceContext *pixelspace) +{ + float *diff_points, *feather_points; + int tot_diff_point, tot_feather_point; + + diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); + + if (!diff_points) + return; + + feather_points = BKE_mask_spline_feather_differentiated_points(spline, pixelspace->aspx, pixelspace->aspy, + &tot_feather_point); + + /* draw feather */ + if (spline->flag & SELECT) + glColor3f(0.0f, 1.0f, 0.0f); + else + glColor3f(0.0f, 0.5f, 0.0f); + draw_dashed_curve(spline, feather_points, tot_feather_point); + + /* draw main curve */ + set_spline_color(shape, spline); + draw_dashed_curve(spline, diff_points, tot_diff_point); + + MEM_freeN(diff_points); + MEM_freeN(feather_points); +} + +static void draw_shapes(Mask *mask, PixelSpaceContext *pixelspace) +{ + MaskShape *shape = mask->shapes.first; + + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + /* draw curve itself first... */ + draw_spline_curve(shape, spline, pixelspace); + + /* ...and then handles over the curve so they're nicely visible */ + draw_spline_points(shape, spline, pixelspace); + + spline = spline->next; + } + + shape = shape->next; + } +} + +void ED_mask_draw(bContext *C, int width, int height, float zoomx, float zoomy) +{ + Mask *mask = CTX_data_edit_mask(C); + PixelSpaceContext pixelspace; + float aspx, aspy; + + if (!mask) + return; + + ED_mask_aspect(C, &aspx, &aspy); + + pixelspace.width = width; + pixelspace.height = height; + pixelspace.zoomx = zoomx; + pixelspace.zoomy = zoomy; + pixelspace.aspx = aspx; + pixelspace.aspy = aspy; + + draw_shapes(mask, &pixelspace); +} diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c new file mode 100644 index 00000000000..fcdf66ed69d --- /dev/null +++ b/source/blender/editors/mask/mask_editor.c @@ -0,0 +1,218 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_ops.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_mask.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" +#include "ED_transform.h" + +#include "RNA_access.h" + +#include "mask_intern.h" // own include + +/********************** generic poll functions *********************/ + +int ED_maskediting_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + return ED_space_clip_maskediting_poll(C); + } + + return FALSE; +} + +int ED_maskediting_mask_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + return ED_space_clip_maskediting_mask_poll(C); + } + + return FALSE; +} + +/********************** registration *********************/ + +void ED_mask_mouse_pos(bContext *C, wmEvent *event, float co[2]) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + ED_clip_mouse_pos(C, event, co); + } + else { + /* possible other spaces from which mask editing is available */ + zero_v2(co); + } +} + +void ED_mask_size(bContext *C, int *width, int *height) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + ED_space_clip_mask_size(sc, width, height); + } + else { + /* possible other spaces from which mask editing is available */ + *width = 0; + *height = 0; + } +} + +void ED_mask_aspect(bContext *C, float *aspx, float *aspy) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + ED_space_clip_mask_aspect(sc, aspx, aspy); + } + else { + /* possible other spaces from which mask editing is available */ + *aspx = 1.0f; + *aspy = 1.0f; + } +} + +void ED_mask_pixelspace_factor(bContext *C, float *scalex, float *scaley) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + ARegion *ar = CTX_wm_region(C); + int width, height; + float zoomx, zoomy, aspx, aspy; + + ED_space_clip_size(sc, &width, &height); + ED_space_clip_zoom(sc, ar, &zoomx, &zoomy); + ED_space_clip_aspect(sc, &aspx, &aspy); + + *scalex = ((float)width * aspx) * zoomx; + *scaley = ((float)height * aspy) * zoomy; + } + else { + /* possible other spaces from which mask editing is available */ + *scalex = 1.0f; + *scaley = 1.0f; + } +} + +/********************** registration *********************/ + +void ED_operatortypes_mask(void) +{ + WM_operatortype_append(MASK_OT_new); + + /* shapes */ + WM_operatortype_append(MASK_OT_shape_new); + WM_operatortype_append(MASK_OT_shape_remove); + + /* geometry */ + WM_operatortype_append(MASK_OT_add_vertex); + WM_operatortype_append(MASK_OT_add_feather_vertex); + WM_operatortype_append(MASK_OT_delete); + + /* select */ + WM_operatortype_append(MASK_OT_select); + WM_operatortype_append(MASK_OT_select_all); + + /* shape */ + WM_operatortype_append(MASK_OT_slide_point); + WM_operatortype_append(MASK_OT_cyclic_toggle); + WM_operatortype_append(MASK_OT_handle_type_set); +} + +void ED_keymap_mask(wmKeyConfig *keyconf) +{ + wmKeyMap *keymap; + wmKeyMapItem *kmi; + + keymap = WM_keymap_find(keyconf, "Mask Editor", 0, 0); + keymap->poll = ED_maskediting_poll; + + WM_keymap_add_item(keymap, "MASK_OT_new", NKEY, KM_PRESS, KM_ALT, 0); + + /* geometry */ + WM_keymap_add_item(keymap, "MASK_OT_add_vertex_slide", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MASK_OT_add_feather_vertex_slide", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "MASK_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_delete", DELKEY, KM_PRESS, 0, 0); + + /* select */ + WM_keymap_add_item(keymap, "MASK_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "extend", TRUE); + + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", AKEY, KM_PRESS, 0, 0); + RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0); + RNA_enum_set(kmi->ptr, "action", SEL_INVERT); + + /* shape */ + WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "MASK_OT_slide_point", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); + + transform_keymap_for_space(keyconf, keymap, SPACE_CLIP); +} + +void ED_operatormacros_mask(void) +{ + /* XXX: just for sample */ + wmOperatorType *ot; + wmOperatorTypeMacro *otmacro; + + ot= WM_operatortype_append_macro("MASK_OT_add_vertex_slide", "Add Vertex and Slide", OPTYPE_UNDO|OPTYPE_REGISTER); + ot->description = "Add new vertex and slide it"; + WM_operatortype_macro_define(ot, "MASK_OT_add_vertex"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_boolean_set(otmacro->ptr, "release_confirm", TRUE); + + ot= WM_operatortype_append_macro("MASK_OT_add_feather_vertex_slide", "Add Feather Vertex and Slide", OPTYPE_UNDO|OPTYPE_REGISTER); + ot->description = "Add new feather vertex and slide it"; + WM_operatortype_macro_define(ot, "MASK_OT_add_feather_vertex"); + otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point"); + RNA_boolean_set(otmacro->ptr, "slide_feather", TRUE); +} diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h new file mode 100644 index 00000000000..073eba3efc9 --- /dev/null +++ b/source/blender/editors/mask/mask_intern.h @@ -0,0 +1,69 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_intern.h + * \ingroup spclip + */ + +#ifndef __MASK_INTERN_H__ +#define __MASK_INTERN_H__ + +struct bContext; +struct wmEvent; +struct wmOperatorType; + +/* internal exports only */ + +/* mask_ops.c */ +void MASK_OT_new(struct wmOperatorType *ot); +void MASK_OT_shape_new(struct wmOperatorType *ot); +void MASK_OT_shape_remove(struct wmOperatorType *ot); + +void MASK_OT_add_vertex(struct wmOperatorType *ot); +void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); +void MASK_OT_cyclic_toggle(struct wmOperatorType *ot); + +void MASK_OT_select(struct wmOperatorType *ot); +void MASK_OT_select_all(struct wmOperatorType *ot); + +void MASK_OT_slide_point(struct wmOperatorType *ot); + +void MASK_OT_delete(struct wmOperatorType *ot); + +void MASK_OT_handle_type_set(struct wmOperatorType *ot); + +/* mask_editor.c */ +int ED_maskediting_poll(struct bContext *C); +int ED_maskediting_mask_poll(struct bContext *C); + +void ED_mask_size(struct bContext *C, int *width, int *height); +void ED_mask_aspect(struct bContext *C, float *aspx, float *aspy); + +void ED_mask_pixelspace_factor(struct bContext *C, float *scalex, float *scaley); +void ED_mask_mouse_pos(struct bContext *C, struct wmEvent *event, float co[2]); + +#endif /* __MASK_INTERN_H__ */ diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c new file mode 100644 index 00000000000..0fedc2b34dc --- /dev/null +++ b/source/blender/editors/mask/mask_ops.c @@ -0,0 +1,1653 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_ops.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" // own include + +/******************** utility functions *********************/ + +static void spline_point_select(MaskSplinePoint *point, int action) +{ + int i; + + switch (action) { + case SEL_SELECT: + MASKPOINT_SEL(point); + break; + case SEL_DESELECT: + MASKPOINT_DESEL(point); + break; + case SEL_INVERT: + MASKPOINT_INVSEL(point); + break; + } + + for (i = 0; i < point->tot_uw; i++) { + switch (action) { + case SEL_SELECT: + point->uw[i].flag |= SELECT; + break; + case SEL_DESELECT: + point->uw[i].flag &= ~SELECT; + break; + case SEL_INVERT: + point->uw[i].flag ^= SELECT; + break; + } + } +} + +static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, float aspx, float aspy, float start_u, float co[2]) +{ + const int N = 1000; + float u = -1.0f, du = 1.0f / N, u1 = start_u, u2 = start_u; + float ang = -1.0f; + + while (u1 > 0.0f || u2 < 1.0d) { + float n1[2], n2[2], co1[2], co2[2]; + float v1[2], v2[2]; + float ang1, ang2; + + if (u1 >= 0.0f) { + BKE_mask_point_segment_co(spline, point, u1, co1); + BKE_mask_point_normal(spline, point, aspx, aspy, u1, n1); + sub_v2_v2v2(v1, co, co1); + + if (len_v2(v1) > 1e-3) { + ang1 = angle_v2v2(v1, n1); + if (ang1 > M_PI / 2.0f) + ang1 = M_PI - ang1; + + if (ang < 0.0f || ang1 < ang) { + ang = ang1; + u = u1; + } + } + else { + u = u1; + break; + } + } + + if (u2 <= 1.0f) { + BKE_mask_point_segment_co(spline, point, u2, co2); + BKE_mask_point_normal(spline, point, aspx, aspy, u2, n2); + sub_v2_v2v2(v2, co, co2); + + if (len_v2(v2) > 1e-3) { + ang2 = angle_v2v2(v2, n2); + if (ang2 > M_PI / 2.0f) + ang2 = M_PI - ang2; + + if (ang2 < ang) { + ang = ang2; + u = u2; + } + } + else { + u = u2; + break; + } + } + + u1 -= du; + u2 += du; + } + + return u; +} + +static int points_has_selection(MaskSplinePoint *points, int tot_point) +{ + int i; + + for (i = 0; i < tot_point; i++) { + MaskSplinePoint *point = &points[i]; + + if (MASKPOINT_ISSEL(point)) + return TRUE; + } + + return FALSE; +} + +static int mask_has_selection(Mask *mask) +{ + MaskShape *shape = mask->shapes.first; + + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + if (points_has_selection(spline->points, spline->tot_point)) + return TRUE; + + spline = spline->next; + } + + shape = shape->next; + } + + return FALSE; +} + +static void toggle_selection_all(Mask *mask, int action) +{ + MaskShape *shape = mask->shapes.first; + + if (action == SEL_TOGGLE) { + if (mask_has_selection(mask)) + action = SEL_DESELECT; + else + action = SEL_SELECT; + } + + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + spline_point_select(point, action); + } + + spline = spline->next; + } + + shape = shape->next; + } +} + +static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal_co[2], int threshold, + MaskShape **shape_r, MaskSpline **spline_r, int *is_handle_r, + float *score) +{ + MaskShape *shape; + MaskShape *point_shape = NULL; + MaskSpline *point_spline = NULL; + MaskSplinePoint *point = NULL; + float co[2], aspx, aspy; + float len = FLT_MAX, scalex, scaley; + int is_handle = FALSE, width, height; + + ED_mask_size(C, &width, &height); + ED_mask_aspect(C, &aspx, &aspy); + ED_mask_pixelspace_factor(C, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *cur_point = &spline->points[i]; + float cur_len, vec[2], handle[2]; + + vec[0] = cur_point->bezt.vec[1][0] * scalex; + vec[1] = cur_point->bezt.vec[1][1] * scaley; + + if (BKE_mask_point_has_handle(cur_point)) { + BKE_mask_point_handle(cur_point, aspx, aspy, handle); + handle[0] *= scalex; + handle[1] *= scaley; + + cur_len = len_v2v2(co, handle); + + if (cur_len < len) { + point_shape = shape; + point_spline = spline; + point = cur_point; + len = cur_len; + is_handle = TRUE; + } + } + + cur_len = len_v2v2(co, vec); + + if (cur_len < len) { + point_spline = spline; + point_shape = shape; + point = cur_point; + len = cur_len; + is_handle = FALSE; + } + } + + spline = spline->next; + } + + shape = shape->next; + } + + if (len < threshold) { + if (shape_r) + *shape_r = point_shape; + + if (spline_r) + *spline_r = point_spline; + + if (is_handle_r) + *is_handle_r = is_handle; + + if (score) + *score = len; + + return point; + } + + if (shape_r) + *shape_r = NULL; + + if (spline_r) + *spline_r = NULL; + + if (is_handle_r) + *is_handle_r = FALSE; + + return NULL; +} + +static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int threshold, + MaskShape **shape_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + MaskSplinePointUW **uw_r, float *score) +{ + MaskShape *shape, *point_shape = NULL; + MaskSpline *point_spline = NULL; + MaskSplinePoint *point = NULL; + MaskSplinePointUW *uw = NULL; + float len = FLT_MAX, co[2]; + float scalex, scaley, aspx, aspy; + int width, height; + + ED_mask_size(C, &width, &height); + ED_mask_aspect(C, &aspx, &aspy); + ED_mask_pixelspace_factor(C, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + int i, tot_feather_point; + float *feather_points, *fp; + + feather_points = fp = BKE_mask_spline_feather_points(spline, aspx, aspy, &tot_feather_point); + + for (i = 0; i < spline->tot_point; i++) { + int j; + MaskSplinePoint *cur_point = &spline->points[i]; + + for (j = 0; j < cur_point->tot_uw + 1; j++) { + float cur_len, vec[2]; + + vec[0] = fp[0] * scalex; + vec[1] = fp[1] * scaley; + + cur_len = len_v2v2(vec, co); + + if (point == NULL || cur_len < len) { + if (j == 0) + uw = NULL; + else + uw = &cur_point->uw[j - 1]; + + point_shape = shape; + point_spline = spline; + point = cur_point; + len = cur_len; + } + + fp += 2; + } + } + + MEM_freeN(feather_points); + + spline = spline->next; + } + + shape = shape->next; + } + + if (len < threshold) { + if (shape_r) + *shape_r = point_shape; + + if (spline_r) + *spline_r = point_spline; + + if (point_r) + *point_r = point; + + if (uw_r) + *uw_r = uw; + + if (score) + *score = len; + + return TRUE; + } + + if (shape_r) + *shape_r = NULL; + + if (spline_r) + *spline_r = NULL; + + if (point_r) + *point_r = NULL; + + return FALSE; +} + +static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], int threshold, int feather, + MaskShape **shape_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + float *u_r, float tangent[2]) +{ + MaskShape *shape, *point_shape; + MaskSpline *point_spline; + MaskSplinePoint *point = NULL; + float dist, co[2]; + int width, height; + float u; + float scalex, scaley, aspx, aspy; + + ED_mask_size(C, &width, &height); + ED_mask_aspect(C, &aspx, &aspy); + ED_mask_pixelspace_factor(C, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *cur_point = &spline->points[i]; + float *diff_points; + int tot_diff_point; + + diff_points = BKE_mask_point_segment_diff(spline, cur_point, &tot_diff_point); + + if (diff_points) { + int i, tot_feather_point, tot_point; + float *feather_points = NULL, *points; + + if (feather) { + feather_points = BKE_mask_point_segment_feather_diff(spline, cur_point, + aspx, aspy, &tot_feather_point); + + points = feather_points; + tot_point = tot_feather_point; + } + else { + points = diff_points; + tot_point = tot_diff_point; + } + + for (i = 0; i < tot_point - 1; i++) { + float cur_dist, a[2], b[2]; + + a[0] = points[2 * i] * scalex; + a[1] = points[2 * i + 1] * scaley; + + b[0] = points[2 * i + 2] * scalex; + b[1] = points[2 * i + 3] * scaley; + + cur_dist = dist_to_line_segment_v2(co, a, b); + + if (point == NULL || cur_dist < dist) { + if (tangent) + sub_v2_v2v2(tangent, &diff_points[2 * i + 2], &diff_points[2 * i]); + + point_shape = shape; + point_spline = spline; + point = cur_point; + dist = cur_dist; + u = (float)i / tot_point; + + } + } + + if (feather_points) + MEM_freeN(feather_points); + } + + MEM_freeN(diff_points); + } + + spline = spline->next; + } + + shape = shape->next; + } + + if (point && dist < threshold) { + if (shape_r) + *shape_r = point_shape; + + if (spline_r) + *spline_r = point_spline; + + if (point_r) + *point_r = point; + + if (u_r) { + u = projection_on_spline(point_spline, point, aspx, aspy, u, normal_co); + + *u_r = u; + } + + return TRUE; + } + + if (shape_r) + *shape_r = NULL; + + if (spline_r) + *spline_r = NULL; + + if (point_r) + *point_r = NULL; + + return FALSE; +} + +static void mask_flush_selection(Mask *mask) +{ + MaskShape *shape; + + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + int i; + + spline->flag &= ~SELECT; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *cur_point = &spline->points[i]; + + if (MASKPOINT_ISSEL(cur_point)) { + spline->flag |= SELECT; + } + else { + int j; + + for (j = 0; j < cur_point->tot_uw; j++) { + if (cur_point->uw[j].flag & SELECT) { + spline->flag |= SELECT; + break; + } + } + } + } + + spline = spline->next; + } + + shape = shape->next; + } +} + +/******************** create new mask *********************/ + +static int mask_new_exec(bContext *C, wmOperator *op) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + Mask *mask; + char name[MAX_ID_NAME-2]; + + RNA_string_get(op->ptr, "name", name); + + mask = BKE_mask_new(name); + + if (sc) + ED_space_clip_set_mask(C, sc, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Mask"; + ot->description = "Create new mask"; + ot->idname = "MASK_OT_new"; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = mask_new_exec; + ot->poll = ED_operator_mask; + + /* properties */ + RNA_def_string(ot->srna, "name", "", MAX_ID_NAME-2, "Name", "Name of new mask"); +} + +/******************** create new shape *********************/ + +static int shape_new_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + char name[MAX_ID_NAME-2]; + + RNA_string_get(op->ptr, "name", name); + + BKE_mask_shape_new(mask, name); + mask->shapenr = mask->tot_shape - 1; + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_shape_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Shape"; + ot->description = "Add new shape for masking"; + ot->idname = "MASK_OT_shape_new"; + + /* api callbacks */ + ot->exec = shape_new_exec; + ot->poll = ED_maskediting_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_string(ot->srna, "name", "", MAX_ID_NAME-2, "Name", "Name of new shape"); +} + +/******************** remove shape *********************/ + +static int shape_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskShape *shape = BKE_mask_shape_active(mask); + + if (shape) { + BKE_mask_shape_remove(mask, shape); + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + } + + return OPERATOR_FINISHED; +} + +void MASK_OT_shape_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Shape"; + ot->description = "Remove shape used for masking"; + ot->idname = "MASK_OT_shape_remove"; + + /* api callbacks */ + ot->exec = shape_remove_exec; + ot->poll = ED_maskediting_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/******************** slide *********************/ + +#define SLIDE_ACTION_NONE 0 +#define SLIDE_ACTION_POINT 1 +#define SLIDE_ACTION_HANDLE 2 +#define SLIDE_ACTION_FEATHER 3 + +typedef struct SlidePointData { + int action; + + float co[2]; + float vec[3][3]; + + Mask *mask; + MaskShape *shape; + MaskSpline *spline; + MaskSplinePoint *point; + MaskSplinePointUW *uw; + float handle[2], no[2], feather[2]; + float aspx, aspy; + int width, height; + float weight; + + short curvature_only, accurate; +} SlidePointData; + +static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) +{ + Mask *mask = CTX_data_edit_mask(C); + SlidePointData *customdata = NULL; + MaskShape *shape, *cv_shape, *feather_shape; + MaskSpline *spline, *cv_spline, *feather_spline; + MaskSplinePoint *point, *cv_point, *feather_point; + MaskSplinePointUW *uw = NULL; + int is_handle = FALSE, width, height, action = SLIDE_ACTION_NONE; + int slide_feather = RNA_boolean_get(op->ptr, "slide_feather"); + float co[2], cv_score, feather_score; + const float threshold = 19; + + ED_mask_mouse_pos(C, event, co); + ED_mask_size(C, &width, &height); + + cv_point = find_nearest_point(C, mask, co, threshold, &cv_shape, &cv_spline, &is_handle, &cv_score); + + if (find_nearest_feather(C, mask, co, threshold, &feather_shape, &feather_spline, &feather_point, &uw, &feather_score)) { + if (slide_feather || !cv_point || feather_score < cv_score) { + action = SLIDE_ACTION_FEATHER; + + shape = feather_shape; + spline = feather_spline; + point = feather_point; + } + } + + if (cv_point && action == SLIDE_ACTION_NONE) { + if (is_handle) + action = SLIDE_ACTION_HANDLE; + else + action = SLIDE_ACTION_POINT; + + shape = cv_shape; + spline = cv_spline; + point = cv_point; + } + + if (action != SLIDE_ACTION_NONE) { + customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data"); + + customdata->mask = mask; + customdata->shape = shape; + customdata->spline = spline; + customdata->point = point; + customdata->width = width; + customdata->height = height; + customdata->action = action; + customdata->uw = uw; + + ED_mask_aspect(C, &customdata->aspx, &customdata->aspy); + + if (uw) { + float co[2]; + + customdata->weight = point->bezt.weight; + + customdata->weight = uw->w; + BKE_mask_point_segment_co(spline, point, uw->u, co); + BKE_mask_point_normal(spline, point, customdata->aspx, customdata->aspy, uw->u, customdata->no); + + customdata->feather[0] = co[0] + customdata->no[0] * uw->w; + customdata->feather[1] = co[1] + customdata->no[1] * uw->w; + } + else { + BezTriple *bezt = &point->bezt; + BKE_mask_point_normal(spline, point, customdata->aspx, customdata->aspy, 0.0f, customdata->no); + + customdata->feather[0] = bezt->vec[1][0] + customdata->no[0] * bezt->weight; + customdata->feather[1] = bezt->vec[1][1] + customdata->no[1] * bezt->weight; + } + + copy_m3_m3(customdata->vec, point->bezt.vec); + if (BKE_mask_point_has_handle(point)) + BKE_mask_point_handle(point, customdata->aspx, customdata->aspy, customdata->handle); + ED_mask_mouse_pos(C, event, customdata->co); + } + + return customdata; +} + +static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + SlidePointData *slidedata = slide_point_customdata(C, op, event); + + if (slidedata) { + Mask *mask = CTX_data_edit_mask(C); + + op->customdata = slidedata; + + WM_event_add_modal_handler(C, op); + + if (slidedata->uw) { + if ((slidedata->uw->flag & SELECT) == 0) { + toggle_selection_all(mask, SEL_DESELECT); + + slidedata->uw->flag |= SELECT; + + mask_flush_selection(mask); + } + } + else if (!MASKPOINT_ISSEL(slidedata->point)) { + toggle_selection_all(mask, SEL_DESELECT); + + spline_point_select(slidedata->point, SEL_SELECT); + + mask_flush_selection(mask); + } + + slidedata->shape->act_spline = slidedata->spline; + slidedata->shape->act_point = slidedata->point; + + WM_event_add_notifier(C, NC_MASK|ND_SELECT, mask); + + return OPERATOR_RUNNING_MODAL; + } + + return OPERATOR_PASS_THROUGH; +} + +static void cancel_slide_point(SlidePointData *data) +{ + /* cancel sliding */ + if (data->action == SLIDE_ACTION_FEATHER) { + if (data->uw) + data->uw->w = data->weight; + else + data->point->bezt.weight = data->weight; + } + else { + copy_m3_m3(data->point->bezt.vec, data->vec); + } +} + +static void free_slide_point_data(SlidePointData *data) +{ + MEM_freeN(data); +} + +static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + SlidePointData *data = (SlidePointData *)op->customdata; + BezTriple *bezt = &data->point->bezt; + float co[2], dco[2]; + + switch(event->type) { + case LEFTCTRLKEY: + case RIGHTCTRLKEY: + case LEFTSHIFTKEY: + case RIGHTSHIFTKEY: + if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) + data->curvature_only = event->val==KM_PRESS; + + if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) + data->accurate = event->val==KM_PRESS; + + /* no break! update CV position */ + + case MOUSEMOVE: + ED_mask_mouse_pos(C, event, co); + sub_v2_v2v2(dco, co, data->co); + + if (data->action == SLIDE_ACTION_HANDLE) { + float delta[2], offco[2]; + + sub_v2_v2v2(delta, data->handle, data->co); + + sub_v2_v2v2(offco, co, data->co); + if (data->accurate) + mul_v2_fl(offco, 0.2f); + add_v2_v2(offco, data->co); + add_v2_v2(offco, delta); + + BKE_mask_point_set_handle(data->point, offco, data->curvature_only, data->aspx, data->aspy, data->handle, data->vec); + } + else if (data->action == SLIDE_ACTION_POINT) { + float delta[2]; + + copy_v2_v2(delta, dco); + if (data->accurate) + mul_v2_fl(delta, 0.2f); + + add_v2_v2v2(bezt->vec[0], data->vec[0], delta); + add_v2_v2v2(bezt->vec[1], data->vec[1], delta); + add_v2_v2v2(bezt->vec[2], data->vec[2], delta); + } + else if (data->action == SLIDE_ACTION_FEATHER) { + float vec[2], no[2], p[2], c[2], w, offco[2]; + float *weight; + + add_v2_v2v2(offco, data->feather, dco); + + if (data->uw) { + float u = projection_on_spline(data->spline, data->point, data->aspx, data->aspy, data->uw->u, offco); + + if (u > 0.0f && u < 1.0f) + data->uw->u = u; + + data->uw = BKE_mask_point_sort_uw(data->point, data->uw); + weight = &data->uw->w; + BKE_mask_point_normal(data->spline, data->point, data->aspx, data->aspy, data->uw->u, no); + BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p); + } + else { + weight = &bezt->weight; + copy_v2_v2(no, data->no); + copy_v2_v2(p, bezt->vec[1]); + } + + sub_v2_v2v2(c, offco, p); + project_v2_v2v2(vec, c, no); + + vec[0] *= data->aspx; + vec[1] *= data->aspy; + + w = len_v2(vec); + + if (dot_v2v2(no, vec) > 0.0f) + *weight = w; + else + *weight = 0; + } + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, data->mask); + DAG_id_tag_update(&data->mask->id, 0); + + break; + + case LEFTMOUSE: + if(event->val==KM_RELEASE) { + free_slide_point_data(op->customdata); + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, data->mask); + DAG_id_tag_update(&data->mask->id, 0); + + return OPERATOR_FINISHED; + } + + break; + + case ESCKEY: + cancel_slide_point(op->customdata); + + free_slide_point_data(op->customdata); + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, data->mask); + DAG_id_tag_update(&data->mask->id, 0); + + return OPERATOR_CANCELLED; + } + + return OPERATOR_RUNNING_MODAL; +} + +void MASK_OT_slide_point(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Slide Point"; + ot->description = "Slide control points"; + ot->idname = "MASK_OT_slide_point"; + + /* api callbacks */ + ot->invoke = slide_point_invoke; + ot->modal = slide_point_modal; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide slide feather instead of vertex"); +} + +/******************** toggle selection *********************/ + +static int select_all_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + int action = RNA_enum_get(op->ptr, "action"); + + toggle_selection_all(mask, action); + mask_flush_selection(mask); + + WM_event_add_notifier(C, NC_MASK|ND_SELECT, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_select_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select or Deselect All"; + ot->description = "Change selection of all curve points"; + ot->idname = "MASK_OT_select_all"; + + /* api callbacks */ + ot->exec = select_all_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_select_all(ot); +} + +/******************** select *********************/ + +static int select_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskShape *shape; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + float co[2]; + int extend = RNA_boolean_get(op->ptr, "extend"); + int is_handle = 0; + const float threshold = 19; + + RNA_float_get_array(op->ptr, "location", co); + + point = find_nearest_point(C, mask, co, threshold, &shape, &spline, &is_handle, NULL); + + if (point) { + if (!extend) + toggle_selection_all(mask, SEL_DESELECT); + + if (is_handle) { + MASKPOINT_HANDLE_SEL(point); + } + else { + spline_point_select(point, SEL_SELECT); + } + + shape->act_spline = spline; + shape->act_point = point; + + mask_flush_selection(mask); + + WM_event_add_notifier(C, NC_MASK|ND_SELECT, mask); + } + else { + MaskSplinePointUW *uw; + + if (find_nearest_feather(C, mask, co, threshold, &shape, &spline, &point, &uw, NULL)) { + if (!extend) + toggle_selection_all(mask, SEL_DESELECT); + + uw->flag |= SELECT; + + shape->act_spline = spline; + shape->act_point = point; + + mask_flush_selection(mask); + + WM_event_add_notifier(C, NC_MASK|ND_SELECT, mask); + } + } + + return OPERATOR_PASS_THROUGH; +} + +static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + float co[2]; + + ED_mask_mouse_pos(C, event, co); + + RNA_float_set_array(op->ptr, "location", co); + + return select_exec(C, op); +} + +void MASK_OT_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select"; + ot->description = "Select spline points"; + ot->idname = "MASK_OT_select"; + + /* api callbacks */ + ot->exec = select_exec; + ot->invoke = select_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "extend", 0, + "Extend", "Extend selection rather than clearing the existing selection"); + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); +} + +/******************** add vertex *********************/ + +static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, + float point_co[2], float tangent[2]) +{ + BezTriple *bezt; + int width, height; + float co[3]; + const float len = 20.0; /* default length of handle in pixel space */ + + copy_v2_v2(co, point_co); + co[2] = 0.0f; + + ED_mask_size(C, &width, &height); + + /* point coordinate */ + bezt = &new_point->bezt; + + bezt->h1 = bezt->h2 = HD_ALIGN; + + copy_v3_v3(bezt->vec[0], co); + copy_v3_v3(bezt->vec[1], co); + copy_v3_v3(bezt->vec[2], co); + + /* initial offset for handles */ + if (spline->tot_point == 1) { + /* first point of splien is aligned horizontally */ + bezt->vec[0][0] -= len / width; + bezt->vec[2][0] += len / width; + } + else if (tangent) { + float vec[2]; + + copy_v2_v2(vec, tangent); + + vec[0] *= width; + vec[1] *= height; + + mul_v2_fl(vec, len / len_v2(vec)); + + vec[0] /= width; + vec[1] /= height; + + sub_v2_v2(bezt->vec[0], vec); + add_v2_v2(bezt->vec[2], vec); + } else { + /* next points are aligning in the direction of previous/next point */ + MaskSplinePoint *point; + float v1[2], v2[2], vec[2]; + float dir = 1.0f; + + if (new_point == spline->points) { + point = new_point + 1; + dir = -1.0f; + } else + point = new_point - 1; + + if (spline->tot_point < 3) { + v1[0] = point->bezt.vec[1][0] * width; + v1[1] = point->bezt.vec[1][1] * height; + + v2[0] = new_point->bezt.vec[1][0] * width; + v2[1] = new_point->bezt.vec[1][1] * height; + } + else { + if (new_point == spline->points) { + v1[0] = spline->points[1].bezt.vec[1][0] * width; + v1[1] = spline->points[1].bezt.vec[1][1] * height; + + v2[0] = spline->points[spline->tot_point - 1].bezt.vec[1][0] * width; + v2[1] = spline->points[spline->tot_point - 1].bezt.vec[1][1] * height; + } + else { + v1[0] = spline->points[0].bezt.vec[1][0] * width; + v1[1] = spline->points[0].bezt.vec[1][1] * height; + + v2[0] = spline->points[spline->tot_point - 2].bezt.vec[1][0] * width; + v2[1] = spline->points[spline->tot_point - 2].bezt.vec[1][1] * height; + } + } + + sub_v2_v2v2(vec, v1, v2); + mul_v2_fl(vec, len * dir / len_v2(vec)); + + vec[0] /= width; + vec[1] /= height; + + add_v2_v2(bezt->vec[0], vec); + sub_v2_v2(bezt->vec[2], vec); + } + + BKE_mask_parent_init(&new_point->parent); + + /* select new point */ + MASKPOINT_SEL(new_point); + mask_flush_selection(mask); +} + +/* **** add subdivide vertex **** */ + +static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) +{ + MaskShape *shape; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + const float threshold = 9; + float tangent[2]; + + if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &shape, &spline, &point, NULL, tangent)) { + MaskSplinePoint *new_point_array, *new_point; + int point_index = point - spline->points; + + toggle_selection_all(mask, SEL_DESELECT); + + new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); + + memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * (point_index + 1)); + memcpy(new_point_array + point_index + 2, spline->points + point_index + 1, + sizeof(MaskSplinePoint) * (spline->tot_point - point_index - 1)); + + MEM_freeN(spline->points); + spline->points = new_point_array; + spline->tot_point++; + + new_point = &new_point_array[point_index + 1]; + + setup_vertex_point(C, mask, spline, new_point, co, tangent); + + shape->act_point = new_point; + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + + return TRUE; + } + + return FALSE; +} + +/* **** add extrude vertex **** */ + +static void finSelectedSplinePoint(MaskShape *shape, MaskSpline **spline, MaskSplinePoint **point) +{ + MaskSpline *cur_spline = shape->splines.first; + + *spline = NULL; + *point = NULL; + + while (cur_spline) { + int i; + + for (i = 0; i < cur_spline->tot_point; i++) { + MaskSplinePoint *cur_point = &cur_spline->points[i]; + + if (MASKPOINT_ISSEL(cur_point)) { + if (*spline != NULL && *spline != cur_spline) { + *spline = NULL; + *point = NULL; + return; + } + else if (*point) { + *point = NULL; + } + else { + *spline = cur_spline; + *point = cur_point; + } + } + } + + cur_spline = cur_spline->next; + } +} + +static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) +{ + MaskShape *shape; + MaskSpline *spline; + MaskSplinePoint *point, *new_point = NULL; + + shape = BKE_mask_shape_active(mask); + + if (!shape) { + /* if there's no shape currently operationg on, create new one */ + shape = BKE_mask_shape_new(mask, ""); + mask->shapenr = mask->tot_shape - 1; + spline = NULL; + point = NULL; + } + else { + finSelectedSplinePoint(shape, &spline, &point); + } + + if (!spline) { + /* no selected splines in actuve shape, create new spline */ + spline = BKE_mask_spline_add(shape); + shape->act_spline = spline; + new_point = spline->points; + } + + if (!new_point) { + MaskSplinePoint *new_point_array; + + if (point == &spline->points[spline->tot_point - 1]) { + MASKPOINT_DESEL(point); + new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); + memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * spline->tot_point); + MEM_freeN(spline->points); + spline->points = new_point_array; + spline->tot_point++; + + new_point = &spline->points[spline->tot_point - 1]; + } + else if (point == &spline->points[0]) { + MASKPOINT_DESEL(point); + new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); + memcpy(new_point_array + 1, spline->points, sizeof(MaskSplinePoint) * spline->tot_point); + MEM_freeN(spline->points); + spline->points = new_point_array; + spline->tot_point++; + + new_point = &spline->points[0]; + } + else { + spline = BKE_mask_spline_add(shape); + shape->act_spline = spline; + new_point = spline->points; + } + } + + shape->act_point = new_point; + + setup_vertex_point(C, mask, spline, new_point, co, NULL); + WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + + return TRUE; +} + +static int add_vertex_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + float co[2]; + + RNA_float_get_array(op->ptr, "location", co); + + if (!add_vertex_subdivide(C, mask, co)) { + if (!add_vertex_extrude(C, mask, co)) + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; +} + +static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + float co[2]; + + ED_mask_mouse_pos(C, event, co); + + RNA_float_set_array(op->ptr, "location", co); + + return add_vertex_exec(C, op); +} + +void MASK_OT_add_vertex(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Vertex"; + ot->description = "Add vertex to active spline"; + ot->idname = "MASK_OT_add_vertex"; + + /* api callbacks */ + ot->exec = add_vertex_exec; + ot->invoke = add_vertex_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); +} + +/******************** add feather vertex *********************/ + +static int add_feather_vertex_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskShape *shape; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + const float threshold = 9; + float co[2], u; + + RNA_float_get_array(op->ptr, "location", co); + + point = find_nearest_point(C, mask, co, threshold, NULL, NULL, NULL, NULL); + if (point) + return OPERATOR_FINISHED; + + if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &shape, &spline, &point, &u, NULL)) { + float w = BKE_mask_point_weight(spline, point, u); + + BKE_mask_point_add_uw(point, u, w); + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +static int add_feather_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + float co[2]; + + ED_mask_mouse_pos(C, event, co); + + RNA_float_set_array(op->ptr, "location", co); + + return add_feather_vertex_exec(C, op); +} + +void MASK_OT_add_feather_vertex(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add feather Vertex"; + ot->description = "Add vertex to feather"; + ot->idname = "MASK_OT_add_feather_vertex"; + + /* api callbacks */ + ot->exec = add_feather_vertex_exec; + ot->invoke = add_feather_vertex_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); +} + +/******************** toggle cyclic *********************/ + +static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskShape *shape = mask->shapes.first; + + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + if (points_has_selection(spline->points, spline->tot_point)) + spline->flag ^= MASK_SPLINE_CYCLIC; + + spline = spline->next; + } + + shape = shape->next; + } + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_cyclic_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Toggle Cyclic"; + ot->description = "Toggle cyclic for selected splines"; + ot->idname = "MASK_OT_cyclic_toggle"; + + /* api callbacks */ + ot->exec = cyclic_toggle_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/******************** delete *********************/ + +static void delete_feather_points(MaskSplinePoint *point) +{ + int i, count = 0; + + if (!point->tot_uw) + return; + + for (i = 0; i < point->tot_uw; i++) { + if ((point->uw[i].flag & SELECT) == 0) + count++; + } + + if (count == 0) { + MEM_freeN(point->uw); + point->uw = NULL; + point->tot_uw = 0; + } + else { + MaskSplinePointUW *new_uw; + int j = 0; + + new_uw = MEM_callocN(count * sizeof(MaskSplinePointUW), "new mask uw points"); + + for (i = 0; i < point->tot_uw; i++) { + if ((point->uw[i].flag & SELECT) == 0) { + new_uw[j++] = point->uw[i]; + } + } + + MEM_freeN(point->uw); + + point->uw = new_uw; + point->tot_uw = count; + } +} + +static int delete_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskShape *shape = mask->shapes.first; + + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + int i, count = 0; + MaskSpline *next_spline = spline->next; + + /* count unselected points */ + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (!MASKPOINT_ISSEL(point)) + count++; + } + + if (count == 0) { + /* delete the whole spline */ + BLI_remlink(&shape->splines, spline); + BKE_mask_spline_free(spline); + + if (spline == shape->act_spline) { + shape->act_spline = NULL; + shape->act_point = NULL; + } + } + else { + MaskSplinePoint *new_points; + int j; + + new_points = MEM_callocN(count*sizeof(MaskSplinePoint), "deleteMaskPoints"); + + for (i = 0, j = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (!MASKPOINT_ISSEL(point)) { + if (point == shape->act_point) + shape->act_point = &new_points[j]; + + delete_feather_points(point); + + new_points[j] = *point; + j++; + } + else { + if (point == shape->act_point) + shape->act_point = NULL; + + BKE_mask_point_free(point); + } + } + + MEM_freeN(spline->points); + spline->points = new_points; + spline->tot_point = j; + + mask_flush_selection(mask); + } + + spline = next_spline; + } + + shape = shape->next; + } + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete"; + ot->description = "Delete selected control points or splines"; + ot->idname = "MASK_OT_delete"; + + /* api callbacks */ + ot->invoke = WM_operator_confirm; + ot->exec = delete_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/******************** set handle type *********************/ + +static int set_handle_type_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskShape *shape = mask->shapes.first; + int handle_type = RNA_enum_get(op->ptr, "type"); + + while (shape) { + MaskSpline *spline = shape->splines.first; + int i; + + while (spline) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL(point)) { + BezTriple *bezt = &point->bezt; + + bezt->h1 = bezt->h2 = handle_type; + } + } + + spline = spline->next; + } + + shape = shape->next; + } + + WM_event_add_notifier(C, NC_MASK|ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; +} + +void MASK_OT_handle_type_set(wmOperatorType *ot) +{ + static EnumPropertyItem editcurve_handle_type_items[]= { + {HD_AUTO, "AUTO", 0, "Auto", ""}, + {HD_VECT, "VECTOR", 0, "Vector", ""}, + {HD_ALIGN, "ALIGNED", 0, "Aligned", ""}, + {0, NULL, 0, NULL, NULL}}; + + /* identifiers */ + ot->name = "Set Handle Type"; + ot->description = "Set type of handles for selected control points"; + ot->idname = "MASK_OT_handle_type_set"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = set_handle_type_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type"); +} diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 49672b77d43..e6fa4d43851 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -69,6 +69,7 @@ #include "ED_screen_types.h" #include "ED_keyframes_draw.h" #include "ED_view3d.h" +#include "ED_clip.h" #include "RNA_access.h" #include "RNA_define.h" @@ -449,6 +450,13 @@ int ED_operator_editmball(bContext *C) return 0; } +int ED_operator_mask(bContext *C) +{ + SpaceClip *sc= CTX_wm_space_clip(C); + + return ED_space_clip_show_maskedit(sc); +} + /* *************************** action zone operator ************************** */ /* operator state vars used: diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 31243184961..6733d95ad71 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -62,6 +62,7 @@ #include "ED_mball.h" #include "ED_logic.h" #include "ED_clip.h" +#include "ED_mask.h" /* only call once on startup, storage is global in BKE kernel listbase */ void ED_spacetypes_init(void) @@ -111,6 +112,7 @@ void ED_spacetypes_init(void) ED_operatortypes_sound(); ED_operatortypes_render(); ED_operatortypes_logic(); + ED_operatortypes_mask(); UI_view2d_operatortypes(); UI_buttons_operatortypes(); @@ -133,6 +135,7 @@ void ED_spacetypes_init(void) ED_operatormacros_action(); ED_operatormacros_clip(); ED_operatormacros_curve(); + ED_operatormacros_mask(); /* register dropboxes (can use macros) */ spacetypes = BKE_spacetypes_list(); @@ -164,6 +167,7 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf) ED_keymap_physics(keyconf); ED_keymap_metaball(keyconf); ED_keymap_paint(keyconf); + ED_keymap_mask(keyconf); ED_marker_keymap(keyconf); UI_view2d_keymap(keyconf); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index e61580295fc..2e7de318299 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -34,10 +34,12 @@ #include "MEM_guardedalloc.h" #include "BKE_main.h" +#include "BKE_mask.h" #include "BKE_movieclip.h" #include "BKE_context.h" #include "BKE_tracking.h" +#include "DNA_mask_types.h" #include "DNA_object_types.h" /* SELECT */ #include "BLI_utildefines.h" @@ -116,6 +118,32 @@ int ED_space_clip_tracking_frame_poll(bContext *C) return FALSE; } +int ED_space_clip_maskediting_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc && sc->clip) { + return ED_space_clip_show_maskedit(sc); + } + + return FALSE; +} + +int ED_space_clip_maskediting_mask_poll(bContext *C) +{ + if (ED_space_clip_maskediting_poll(C)) { + MovieClip *clip = CTX_data_edit_movieclip(C); + + if (clip) { + SpaceClip *sc= CTX_wm_space_clip(C); + + return sc->mask != NULL; + } + } + + return FALSE; +} + /* ******** editing functions ******** */ void ED_space_clip_set(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip) @@ -159,6 +187,11 @@ MovieClip *ED_space_clip(SpaceClip *sc) return sc->clip; } +Mask *ED_space_clip_mask(SpaceClip *sc) +{ + return sc->mask; +} + ImBuf *ED_space_clip_get_buffer(SpaceClip *sc) { if (sc->clip) { @@ -203,6 +236,42 @@ void ED_space_clip_size(SpaceClip *sc, int *width, int *height) } } +void ED_space_clip_mask_size(SpaceClip *sc, int *width, int *height) +{ + if(!sc->mask) { + *width= 0; + *height= 0; + } else { + float aspx, aspy; + + ED_space_clip_size(sc, width, height); + ED_space_clip_aspect(sc, &aspx, &aspy); + + *width *= aspx; + *height *= aspy; + } +} + +void ED_space_clip_mask_aspect(SpaceClip *sc, float *aspx, float *aspy) +{ + int w, h; + + ED_space_clip_aspect(sc, aspx, aspy); + ED_space_clip_size(sc, &w, &h); + + *aspx *= (float)w; + *aspy *= (float)h; + + if(*aspx < *aspy) { + *aspy= *aspy / *aspx; + *aspx= 1.0f; + } + else { + *aspx= *aspx / *aspy; + *aspy= 1.0f; + } +} + void ED_space_clip_zoom(SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy) { int width, height; @@ -557,6 +626,8 @@ void ED_space_clip_free_texture_buffer(SpaceClip *sc) } } +/* ******** masking editing related functions ******** */ + int ED_space_clip_show_trackedit(SpaceClip *sc) { if (sc) { @@ -573,3 +644,23 @@ void ED_space_clip_update_dopesheet(SpaceClip *sc) BKE_tracking_update_dopesheet(tracking); } + +int ED_space_clip_show_maskedit(SpaceClip *sc) +{ + if (sc) { + return sc->mode == SC_MODE_MASKEDITING; + } + + return FALSE; +} + +void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask) +{ + sc->mask = mask; + + if(sc->mask && sc->mask->id.us==0) + sc->clip->id.us = 1; + + if(C) + WM_event_add_notifier(C, NC_MASK|NA_SELECTED, mask); +} diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 80db32303cb..04b1c92cf8e 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -33,6 +33,7 @@ #include #include "DNA_scene_types.h" +#include "DNA_mask_types.h" #include "DNA_movieclip_types.h" #include "MEM_guardedalloc.h" @@ -49,6 +50,7 @@ #include "IMB_imbuf_types.h" +#include "ED_mask.h" #include "ED_screen.h" #include "ED_clip.h" #include "ED_transform.h" @@ -357,6 +359,23 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) break; } break; + case NC_MASK: + switch(wmn->data) { + case ND_SELECT: + case ND_DATA: + ED_area_tag_redraw(sa); + break; + } + switch(wmn->action) { + case NA_SELECTED: + clip_scopes_tag_refresh(sa); + ED_area_tag_redraw(sa); + break; + case NA_EDITED: + ED_area_tag_redraw(sa); + break; + } + break; case NC_GEOM: switch (wmn->data) { case ND_SELECT: @@ -710,7 +729,7 @@ static void clip_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "extend", TRUE); /* toggle */ } -const char *clip_context_dir[]= {"edit_movieclip", NULL}; +const char *clip_context_dir[]= {"edit_movieclip", "edit_mask", NULL}; static int clip_context(const bContext *C, const char *member, bContextDataResult *result) { @@ -724,7 +743,11 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul else if (CTX_data_equals(member, "edit_movieclip")) { if (sc->clip) CTX_data_id_pointer_set(result, &sc->clip->id); - + return TRUE; + } + else if (CTX_data_equals(member, "edit_mask")) { + if (sc->mask) + CTX_data_id_pointer_set(result, &sc->mask->id); return TRUE; } @@ -996,6 +1019,9 @@ static void clip_main_area_init(wmWindowManager *wm, ARegion *ar) keymap = WM_keymap_find(wm->defaultconf, "Clip Editor", SPACE_CLIP, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + + keymap= WM_keymap_find(wm->defaultconf, "Mask Editor", 0, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } static void clip_main_area_draw(const bContext *C, ARegion *ar) @@ -1038,6 +1064,29 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) /* Grease Pencil */ clip_draw_grease_pencil((bContext *)C, 1); + if(sc->mode == SC_MODE_MASKEDITING) { + int x, y; + int width, height; + float zoomx, zoomy, aspx, aspy; + + /* find window pixel coordinates of origin */ + UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); + + ED_space_clip_size(sc, &width, &height); + ED_space_clip_zoom(sc, ar, &zoomx, &zoomy); + ED_space_clip_aspect(sc, &aspx, &aspy); + + /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */ + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef(width*zoomx, height*zoomy, 0); + glMultMatrixf(sc->stabmat); + + ED_mask_draw((bContext *)C, width*aspx, height*aspy, zoomx, zoomy); + + glPopMatrix(); + } + /* reset view matrix */ UI_view2d_view_restore(C); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index bd17c821567..883eb962c0c 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1942,6 +1942,11 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po uiItemR(layout, ptr, "distortion_type", 0, "", 0); } +static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL); +} + /* only once called */ static void node_composit_set_butfunc(bNodeType *ntype) { @@ -2108,6 +2113,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_MOVIEDISTORTION: ntype->uifunc= node_composit_buts_moviedistortion; break; + case CMP_NODE_MASK: + ntype->uifunc= node_composit_buts_mask; + break; default: ntype->uifunc= NULL; } diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 3540c20e515..119b350052e 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -250,6 +250,13 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) break; } break; + case NC_MASK: + if (wmn->action == NA_EDITED) { + if (type==NTREE_COMPOSIT) { + ED_area_tag_refresh(sa); + } + } + break; case NC_IMAGE: if (wmn->action == NA_EDITED) { diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 6d72ca99678..5fe8444fe65 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -49,6 +49,7 @@ #include "DNA_constraint_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_mask_types.h" #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" /* PET modes */ @@ -169,6 +170,13 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) r_vec[0] = (v2d->cur.xmax-v2d->cur.xmin)*(dx)/divx; r_vec[1] = (v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy; r_vec[2] = 0.0f; + + if (t->options & CTX_MASK) { + float aspx, aspy; + ED_space_clip_mask_aspect(t->sa->spacedata.first, &aspx, &aspy); + r_vec[0] *= aspx; + r_vec[1] *= aspy; + } } else { printf("%s: called in an invalid context\n", __func__); @@ -229,6 +237,19 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) copy_v2_v2(v, vec); + if (t->options & CTX_MASK) { + float aspx, aspy; + ED_space_clip_aspect(t->sa->spacedata.first, &aspx, &aspy); + v[0] /= aspx; + v[1] /= aspy; + } + else if (t->options & CTX_MASK) { + float aspx, aspy; + ED_space_clip_mask_aspect(t->sa->spacedata.first, &aspx, &aspy); + v[0] /= aspx; + v[1] /= aspy; + } + UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1); } } @@ -279,13 +300,15 @@ void applyAspectRatio(TransInfo *t, float *vec) vec[1] /= aspy; } else if ((t->spacetype==SPACE_CLIP) && (t->mode==TFM_TRANSLATION)) { - if (t->options & CTX_MOVIECLIP) { + if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { SpaceClip *sc = t->sa->spacedata.first; float aspx, aspy; int width, height; - ED_space_clip_size(sc, &width, &height); - ED_space_clip_aspect(sc, &aspx, &aspy); + if (t->options & CTX_MOVIECLIP) + ED_space_clip_size(sc, &width, &height); + else if (t->options & CTX_MASK) + ED_space_clip_aspect(sc, &aspx, &aspy); vec[0] *= width / aspx; vec[1] *= height / aspy; @@ -312,13 +335,15 @@ void removeAspectRatio(TransInfo *t, float *vec) vec[1] *= aspy; } else if ((t->spacetype==SPACE_CLIP) && (t->mode==TFM_TRANSLATION)) { - if (t->options & CTX_MOVIECLIP) { + if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { SpaceClip *sc = t->sa->spacedata.first; float aspx, aspy; int width, height; - ED_space_clip_size(sc, &width, &height); - ED_space_clip_aspect(sc, &aspx, &aspy); + if (t->options & CTX_MOVIECLIP) + ED_space_clip_size(sc, &width, &height); + else if (t->options & CTX_MASK) + ED_space_clip_aspect(sc, &aspx, &aspy); vec[0] *= aspx / width; vec[1] *= aspy / height; @@ -367,12 +392,20 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) } else if (t->spacetype==SPACE_CLIP) { SpaceClip *sc = (SpaceClip*)t->sa->spacedata.first; - MovieClip *clip = ED_space_clip(sc); - /* objects could be parented to tracking data, so send this for viewport refresh */ - WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); + if (ED_space_clip_show_trackedit(sc)) { + MovieClip *clip = ED_space_clip(sc); - WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip); + /* objects could be parented to tracking data, so send this for viewport refresh */ + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); + + WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip); + } + else if (ED_space_clip_show_maskedit(sc)) { + Mask *mask = ED_space_clip_mask(sc); + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + } } } @@ -654,7 +687,7 @@ int transformEvent(TransInfo *t, wmEvent *event) t->redraw |= TREDRAW_HARD; } else if (t->mode == TFM_TRANSLATION) { - if(t->options & CTX_MOVIECLIP) { + if(t->options & (CTX_MOVIECLIP | CTX_MASK)) { restoreTransObjects(t); t->flag ^= T_ALT_TRANSFORM; @@ -1591,9 +1624,13 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_CLIP) { + SpaceClip *sc = CTX_wm_space_clip(C); unit_m3(t->spacemtx); t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->options |= CTX_MOVIECLIP; + if (ED_space_clip_show_trackedit(sc)) + t->options |= CTX_MOVIECLIP; + else if (ED_space_clip_show_maskedit(sc)) + t->options |= CTX_MASK; } else unit_m3(t->spacemtx); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 69af8cf2489..3fb86acf697 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -546,6 +546,7 @@ int clipUVTransform(TransInfo *t, float *vec, int resize); void flushTransNodes(TransInfo *t); void flushTransSeq(TransInfo *t); void flushTransTracking(TransInfo *t); +void flushTransMasking(TransInfo *t); /*********************** exported from transform_manipulator.c ********** */ int gimbal_axis(struct Object *ob, float gmat[][3]); /* return 0 when no gimbal for selection */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index ecd69f0d10c..85e970a0441 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -53,6 +53,7 @@ #include "DNA_meshdata_types.h" #include "DNA_gpencil_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "MEM_guardedalloc.h" @@ -87,6 +88,7 @@ #include "BKE_sequencer.h" #include "BKE_tessmesh.h" #include "BKE_tracking.h" +#include "BKE_mask.h" #include "ED_anim_api.h" @@ -102,6 +104,7 @@ #include "ED_types.h" #include "ED_uvedit.h" #include "ED_clip.h" +#include "ED_mask.h" #include "ED_util.h" /* for crazyspace correction */ #include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */ @@ -4848,6 +4851,17 @@ void special_aftertrans_update(bContext *C, TransInfo *t) WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); } } + else if (t->options & CTX_MASK) { + SpaceClip *sc = t->sa->spacedata.first; + Mask *mask = ED_space_clip_mask(sc); + + if (t->scene->nodetree) { + /* tracks can be used for stabilization nodes, + * flush update for such nodes */ + nodeUpdateID(t->scene->nodetree, &mask->id); + WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); + } + } } else if (t->spacetype == SPACE_ACTION) { SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; @@ -5773,6 +5787,197 @@ void flushTransTracking(TransInfo *t) } } +/* * masking * */ + +typedef struct TransDataMasking{ + float is_handle; + + float handle[2], orig_handle[2]; + float vec[3][3]; + MaskSplinePoint *point; +} TransDataMasking; + +static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, TransData *td, TransData2D *td2d, TransDataMasking *tdm) +{ + BezTriple *bezt = &point->bezt; + float aspx, aspy; + + tdm->point = point; + copy_m3_m3(tdm->vec, bezt->vec); + + ED_space_clip_mask_aspect(sc, &aspx, &aspy); + + if (MASKPOINT_CV_ISSEL(point)) { + int i; + for (i = 0; i < 3; i++) { + /* CV coords are scaled by aspects. this is needed for rotations and + * proportional editing to be consistent with the stretched CV coords + * that are displayed. this also means that for display and numinput, + * and when the the CV coords are flushed, these are converted each time */ + td2d->loc[0] = bezt->vec[i][0]*aspx; + td2d->loc[1] = bezt->vec[i][1]*aspy; + td2d->loc[2] = 0.0f; + td2d->loc2d = bezt->vec[i]; + + td->flag = 0; + td->loc = td2d->loc; + copy_v3_v3(td->center, td->loc); + copy_v3_v3(td->iloc, td->loc); + + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext= NULL; + td->val= NULL; + + td->flag |= TD_SELECTED; + td->dist= 0.0; + + unit_m3(td->mtx); + unit_m3(td->smtx); + + td++; + td2d++; + } + } + else { + int width, height; + + tdm->is_handle = TRUE; + + ED_space_clip_mask_size(sc, &width, &height); + BKE_mask_point_handle(point, width, height, tdm->handle); + + copy_v2_v2(tdm->orig_handle, tdm->handle); + + td2d->loc[0] = tdm->handle[0]*aspx; + td2d->loc[1] = tdm->handle[1]*aspy; + td2d->loc[2] = 0.0f; + td2d->loc2d = tdm->handle; + + td->flag = 0; + td->loc = td2d->loc; + copy_v3_v3(td->center, td->loc); + copy_v3_v3(td->iloc, td->loc); + + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext= NULL; + td->val= NULL; + + td->flag |= TD_SELECTED; + td->dist= 0.0; + + unit_m3(td->mtx); + unit_m3(td->smtx); + + td++; + td2d++; + } +} + +static void createTransMaskingData(bContext *C, TransInfo *t) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + Mask *mask = CTX_data_edit_mask(C); + MaskShape *shape; + TransData *td = NULL; + TransData2D *td2d = NULL; + TransDataMasking *tdm = NULL; + + /* count */ + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL(point)) { + if (MASKPOINT_CV_ISSEL(point)) + t->total += 3; + else + t->total += 1; + } + } + + spline = spline->next; + } + + shape = shape->next; + } + + if (t->total == 0) + return; + + td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransObData(Mask Editing)"); + /* for each 2d uv coord a 3d vector is allocated, so that they can be + * treated just as if they were 3d verts */ + td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(Mask Editing)"); + tdm = t->customData = MEM_callocN(t->total*sizeof(TransDataMasking), "TransDataMasking(Mask Editing)"); + + t->flag |= T_FREE_CUSTOMDATA; + + /* create data */ + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL(point)) { + MaskPointToTransData(sc, point, td, td2d, tdm); + + if (MASKPOINT_CV_ISSEL(point)) { + td += 3; + td2d += 3; + tdm += 3; + } + else { + td++; + td2d++; + tdm++; + } + } + } + + spline = spline->next; + } + + shape = shape->next; + } +} + +void flushTransMasking(TransInfo *t) +{ + SpaceClip *sc = t->sa->spacedata.first; + TransData2D *td; + TransDataMasking *tdm; + int a; + float aspx, aspy, invx, invy; + + ED_space_clip_mask_aspect(sc, &aspx, &aspy); + invx = 1.0f/aspx; + invy = 1.0f/aspy; + + /* flush to 2d vector from internally used 3d vector */ + for(a=0, td = t->data2d, tdm = t->customData; atotal; a++, td++, tdm++) { + td->loc2d[0]= td->loc[0]*invx; + td->loc2d[1]= td->loc[1]*invy; + + if (tdm->is_handle) + BKE_mask_point_set_handle(tdm->point, td->loc2d, t->flag & T_ALT_TRANSFORM, aspx, aspy, tdm->orig_handle, tdm->vec); + } +} + void createTransData(bContext *C, TransInfo *t) { Scene *scene = t->scene; @@ -5842,6 +6047,8 @@ void createTransData(bContext *C, TransInfo *t) t->flag |= T_POINTS|T_2D_EDIT; if (t->options & CTX_MOVIECLIP) createTransTrackingData(C, t); + else if (t->options & CTX_MASK) + createTransMaskingData(C, t); } else if (t->obedit) { t->ext = NULL; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 0bf02d1a2bf..7f6cc9ca336 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -49,6 +49,7 @@ #include "DNA_view3d_types.h" #include "DNA_modifier_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "BLI_math.h" #include "BLI_blenlib.h" @@ -637,33 +638,42 @@ static void recalcData_spaceclip(TransInfo *t) { SpaceClip *sc = t->sa->spacedata.first; - MovieClip *clip = ED_space_clip(sc); - ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); - MovieTrackingTrack *track; + if (ED_space_clip_show_trackedit(sc)) { + MovieClip *clip = ED_space_clip(sc); + ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); + MovieTrackingTrack *track; - flushTransTracking(t); + flushTransTracking(t); - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { - if (t->mode == TFM_TRANSLATION) { - if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_POS); - if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS); - } - else if (t->mode == TFM_RESIZE) { - if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); - if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); + track = tracksbase->first; + while (track) { + if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { + if (t->mode == TFM_TRANSLATION) { + if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) + BKE_tracking_clamp_track(track, CLAMP_PAT_POS); + if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) + BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS); + } + else if (t->mode == TFM_RESIZE) { + if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) + BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); + if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) + BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); + } } + + track = track->next; } - track = track->next; + DAG_id_tag_update(&clip->id, 0); } + else if (ED_space_clip_show_maskedit(sc)) { + Mask *mask = ED_space_clip_mask(sc); - DAG_id_tag_update(&clip->id, 0); + flushTransMasking(t); + + DAG_id_tag_update(&mask->id, 0); + } } /* helper for recalcData() - for 3d-view transforms */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 83d4a5dfa6e..06355d623eb 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -967,6 +967,7 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, OP_TRANSLATION, EVT_TWEAK_S, KM_ANY, 0, 0); WM_keymap_add_item(keymap, OP_RESIZE, SKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, OP_ROTATION, RKEY, KM_PRESS, 0, 0); break; default: break; diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 1737f3b79e6..2c664a7de21 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -207,6 +207,7 @@ typedef struct PreviewImage { #define ID_GD MAKE_ID2('G', 'D') /* GreasePencil */ #define ID_WM MAKE_ID2('W', 'M') /* WindowManager */ #define ID_MC MAKE_ID2('M', 'C') /* MovieClip */ +#define ID_MSK MAKE_ID2('M', 'S') /* Mask */ /* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */ #define ID_SEQ MAKE_ID2('S', 'Q') diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h new file mode 100644 index 00000000000..7597a21fd03 --- /dev/null +++ b/source/blender/makesdna/DNA_mask_types.h @@ -0,0 +1,108 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file DNA_mask_types.h + * \ingroup DNA + * \since march-2012 + * \author Sergey Sharybin + */ + +#ifndef __DNA_MASK_TYPES_H__ +#define __DNA_MASK_TYPES_H__ + +#include "DNA_defs.h" +#include "DNA_ID.h" +#include "DNA_listBase.h" +#include "DNA_curve_types.h" + +typedef struct Mask { + ID id; + struct AnimData *adt; + ListBase shapes; /* shapes which defines this mask */ + int shapenr; /* index of active shape */ + int tot_shape; /* total number of shapes */ +} Mask; + +typedef struct MaskParent { + int flag; /* parenting flags */ + int id_type; /* type of parenting */ + ID *id; /* ID block of entity to which mask/spline is parented to + * in case of parenting to movie tracking data set to MovieClip datablock */ + char parent[64]; /* entity of parent to which parenting happened + * in case of parenting to movie tracking data contains name of object */ + char sub_parent[64]; /* sub-entity of parent to which parenting happened + * in case of parenting to movie tracking data contains name of track */ + float offset[2]; /* offset from parent position, so object/control point can be parented to a + * motion track and also be animated (see ZanQdo's request below) */ +} MaskParent; + +typedef struct MaskSplinePointUW { + float u, w; /* u coordinate along spline segment and weight of this point */ + int flag; /* different flags of this point */ +} MaskSplinePointUW; + +typedef struct MaskSplinePoint { + BezTriple bezt; /* actual point coordinates and it's handles */ + int pad; + int tot_uw; /* number of uv feather values */ + MaskSplinePointUW *uw; /* feather UV values */ + MaskParent parent; /* parenting information of particular spline point */ +} MaskSplinePoint; + +typedef struct MaskSpline { + struct MaskSpline *next, *prev; + + int flag; /* defferent spline flag (closed, ...) */ + int tot_point; /* total number of points */ + MaskSplinePoint *points; /* points which defines spline itself */ + MaskParent parent; /* parenting information of the whole spline */ + + int weight_interp, pad; /* weight interpolation */ +} MaskSpline; + +typedef struct MaskShape { + struct MaskShape *next, *prev; + + char name[64]; /* name of the shape (64 = MAD_ID_NAME - 2) */ + + ListBase splines; /* list of splines which defines this shape */ + struct MaskSpline *act_spline; /* active spline */ + struct MaskSplinePoint *act_point; /* active point */ +} MaskShape; + +/* MaskParent->flag */ +#define MASK_PARENT_ACTIVE (1<<0) + +/* MaskSpline->flag */ +#define MASK_SPLINE_CYCLIC (1<<1) + +/* MaskSpline->weight_interp */ +#define MASK_SPLINE_INTERP_LINEAR 1 +#define MASK_SPLINE_INTERP_EASE 2 + +#endif // __DNA_MASK_TYPES_H__ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index c2fbc611bc3..ad13f5047d5 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -67,6 +67,7 @@ struct wmOperator; struct wmTimer; struct MovieClip; struct MovieClipScopes; +struct Mask; /** * The base structure all the other spaces @@ -523,6 +524,9 @@ typedef struct SpaceClip { int postproc_flag, pad2; void *draw_context; + + /* **** mask editing **** */ + struct Mask *mask; } SpaceClip; /* view3d Now in DNA_view3d_types.h */ @@ -910,6 +914,7 @@ enum { #define SC_MODE_TRACKING 0 #define SC_MODE_RECONSTRUCTION 1 #define SC_MODE_DISTORTION 2 +#define SC_MODE_MASKEDITING 3 /* SpaceClip->view */ #define SC_VIEW_CLIP 0 diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index adcdf5df106..d66682b8e0a 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -132,6 +132,7 @@ static const char *includefiles[] = { "DNA_movieclip_types.h", "DNA_tracking_types.h", "DNA_dynamicpaint_types.h", + "DNA_mask_types.h", // empty string to indicate end of includefiles "" @@ -1239,4 +1240,5 @@ int main(int argc, char ** argv) #include "DNA_movieclip_types.h" #include "DNA_tracking_types.h" #include "DNA_dynamicpaint_types.h" +#include "DNA_mask_types.h" /* end of list */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 316ea46d159..de2edbea845 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -145,6 +145,7 @@ extern StructRNA RNA_CompositorNodeLumaMatte; extern StructRNA RNA_CompositorNodeMapUV; extern StructRNA RNA_CompositorNodeMapValue; extern StructRNA RNA_CompositorNodeMath; +extern StructRNA RNA_CompositorNodeMask; extern StructRNA RNA_CompositorNodeMixRGB; extern StructRNA RNA_CompositorNodeNormal; extern StructRNA RNA_CompositorNodeNormalize; @@ -304,6 +305,7 @@ extern StructRNA RNA_MaterialStrand; extern StructRNA RNA_MaterialSubsurfaceScattering; extern StructRNA RNA_MaterialTextureSlot; extern StructRNA RNA_MaterialVolume; +extern StructRNA RNA_Mask; extern StructRNA RNA_Menu; extern StructRNA RNA_Mesh; extern StructRNA RNA_MeshColor; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 6f8e7656a83..71c03858d00 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -56,6 +56,7 @@ set(DEFSRC rna_lamp.c rna_lattice.c rna_main.c + rna_mask.c rna_material.c rna_mesh.c rna_meta.c diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 62957ac5de8..1a4e8b3d5a7 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2679,6 +2679,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_world.c", NULL, RNA_def_world}, {"rna_movieclip.c", NULL, RNA_def_movieclip}, {"rna_tracking.c", NULL, RNA_def_tracking}, + {"rna_mask.c", NULL, RNA_def_mask}, {NULL, NULL}}; static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const char *api_filename) diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 6992d992cca..0be95645a07 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -144,6 +144,7 @@ short RNA_type_to_ID_code(StructRNA *type) if (RNA_struct_is_a(type, &RNA_World)) return ID_WO; if (RNA_struct_is_a(type, &RNA_WindowManager)) return ID_WM; if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC; + if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK; return 0; } @@ -179,6 +180,7 @@ StructRNA *ID_code_to_RNA_type(short idcode) case ID_WO: return &RNA_World; case ID_WM: return &RNA_WindowManager; case ID_MC: return &RNA_MovieClip; + case ID_MSK: return &RNA_Mask; default: return &RNA_ID; } } diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 155c9c67e4a..b52465fce57 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -179,6 +179,7 @@ void RNA_def_wm(struct BlenderRNA *brna); void RNA_def_world(struct BlenderRNA *brna); void RNA_def_movieclip(struct BlenderRNA *brna); void RNA_def_tracking(struct BlenderRNA *brna); +void RNA_def_mask(struct BlenderRNA *brna); /* Common Define functions */ @@ -296,6 +297,7 @@ void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop); /* ID Properties */ diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 1a039295924..a6d7f7d484e 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -253,6 +253,12 @@ static void rna_Main_movieclips_begin(CollectionPropertyIterator *iter, PointerR rna_iterator_listbase_begin(iter, &bmain->movieclip, NULL); } +static void rna_Main_masks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Main *bmain= (Main*)ptr->data; + rna_iterator_listbase_begin(iter, &bmain->mask, NULL); +} + #ifdef UNIT_TEST static PointerRNA rna_Test_test_get(PointerRNA *ptr) @@ -322,6 +328,7 @@ void RNA_def_main(BlenderRNA *brna) RNA_def_main_gpencil}, {"movieclips", "MovieClip", "rna_Main_movieclips_begin", "Movie Clips", "Movie Clip datablocks", RNA_def_main_movieclips}, + {"masks", "Mask", "rna_Main_masks_begin", "Masks", "Masks datablocks", RNA_def_main_masks}, {NULL, NULL, NULL, NULL, NULL, NULL}}; int i; diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 63006af7c72..8f4d1aa97b5 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -33,6 +33,8 @@ #include #include +#include "DNA_ID.h" + #include "RNA_define.h" #include "RNA_access.h" #include "RNA_enum_types.h" @@ -67,6 +69,7 @@ #include "BKE_depsgraph.h" #include "BKE_speaker.h" #include "BKE_movieclip.h" +#include "BKE_mask.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" @@ -87,6 +90,7 @@ #include "DNA_vfont_types.h" #include "DNA_node_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "ED_screen.h" @@ -539,6 +543,22 @@ void rna_Main_movieclips_remove(Main *bmain, MovieClip *clip) /* XXX python now has invalid pointer? */ } +Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name) +{ + Mask *mask; + + mask = BKE_mask_new("Mask"); + + return mask; +} + +void rna_Main_masks_remove(Main *bmain, Mask *mask) +{ + BKE_mask_unlink(bmain, mask); + free_libblock(&bmain->mask, mask); + /* XXX python now has invalid pointer? */ +} + /* tag functions, all the same */ void rna_Main_cameras_tag(Main *bmain, int value) { tag_main_lb(&bmain->camera, value); } void rna_Main_scenes_tag(Main *bmain, int value) { tag_main_lb(&bmain->scene, value); } @@ -569,6 +589,7 @@ void rna_Main_actions_tag(Main *bmain, int value) { tag_main_lb(&bmain->action, void rna_Main_particles_tag(Main *bmain, int value) { tag_main_lb(&bmain->particle, value); } void rna_Main_gpencil_tag(Main *bmain, int value) { tag_main_lb(&bmain->gpencil, value); } void rna_Main_movieclips_tag(Main *bmain, int value) { tag_main_lb(&bmain->movieclip, value); } +void rna_Main_masks_tag(Main *bmain, int value) { tag_main_lb(&bmain->mask, value); } static int rna_Main_cameras_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CA); } static int rna_Main_scenes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SCE); } @@ -1519,4 +1540,34 @@ void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_return(func, parm); } +void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "BlendDataMasks"); + srna= RNA_def_struct(brna, "BlendDataMasks", NULL); + RNA_def_struct_sdna(srna, "Main"); + RNA_def_struct_ui_text(srna, "Main Masks", "Collection of masks"); + + func= RNA_def_function(srna, "tag", "rna_Main_masks_tag"); + parm= RNA_def_boolean(func, "value", 0, "Value", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + + /* new func */ + func = RNA_def_function(srna, "new", "rna_Main_mask_new"); + RNA_def_function_ui_description(func, "Add a new mask with a given name to the main database"); + parm = RNA_def_string_file_path(func, "name", "", MAX_ID_NAME - 2, "Mask", "Name of new mask datablock"); + /* return type */ + parm = RNA_def_pointer(func, "mask", "Mask", "", "New mask datablock"); + RNA_def_function_return(func, parm); + + /* remove func */ + func= RNA_def_function(srna, "remove", "rna_Main_masks_remove"); + RNA_def_function_ui_description(func, "Remove a masks from the current blendfile."); + parm= RNA_def_pointer(func, "mask", "Mask", "", "Mask to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL); +} + #endif diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c new file mode 100644 index 00000000000..3d4a5a39dc2 --- /dev/null +++ b/source/blender/makesrna/intern/rna_mask.c @@ -0,0 +1,600 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/makesrna/intern/rna_mask.c + * \ingroup RNA + */ + + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BKE_movieclip.h" +#include "BKE_tracking.h" + +#include "RNA_define.h" + +#include "rna_internal.h" + +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ +#include "DNA_scene_types.h" + +#include "WM_types.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#ifdef RNA_RUNTIME + +#include "DNA_mask_types.h" + +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "RNA_access.h" + +#include "WM_api.h" + +static void rna_Mask_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + Mask *mask = ptr->id.data; + + WM_main_add_notifier(NC_MASK|ND_DATA, mask); + DAG_id_tag_update( &mask->id, 0); +} + +/* note: this function exists only to avoid id refcounting */ +static void rna_MaskParent_id_set(PointerRNA *ptr, PointerRNA value) +{ + MaskParent *mpar = (MaskParent*) ptr->data; + + mpar->id = value.data; +} + +static StructRNA *rna_MaskParent_id_typef(PointerRNA *ptr) +{ + MaskParent *mpar = (MaskParent*) ptr->data; + + return ID_code_to_RNA_type(mpar->id_type); +} + +static void rna_MaskParent_id_type_set(PointerRNA *ptr, int value) +{ + MaskParent *mpar = (MaskParent*) ptr->data; + + /* change ID-type to the new type */ + mpar->id_type = value; + + /* clear the id-block if the type is invalid */ + if ((mpar->id) && (GS(mpar->id->name) != mpar->id_type)) + mpar->id = NULL; +} + +static void rna_Mask_shapes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Mask *mask = (Mask *)ptr->id.data; + + rna_iterator_listbase_begin(iter, &mask->shapes, NULL); +} + +static int rna_Mask_active_shape_index_get(PointerRNA *ptr) +{ + Mask *mask = (Mask *)ptr->id.data; + + return mask->shapenr; +} + +static void rna_Mask_active_shape_index_set(PointerRNA *ptr, int value) +{ + Mask *mask = (Mask *)ptr->id.data; + + mask->shapenr = value; +} + +static void rna_Mask_active_shape_index_range(PointerRNA *ptr, int *min, int *max) +{ + Mask *mask = (Mask *)ptr->id.data; + + *min = 0; + *max = mask->tot_shape - 1; + *max = MAX2(0, *max); +} + +static PointerRNA rna_Mask_active_shape_get(PointerRNA *ptr) +{ + Mask *mask = (Mask *)ptr->id.data; + MaskShape *shape = BKE_mask_shape_active(mask); + + return rna_pointer_inherit_refine(ptr, &RNA_MaskShape, shape); +} + +static void rna_Mask_active_shape_set(PointerRNA *ptr, PointerRNA value) +{ + Mask *mask = (Mask *)ptr->id.data; + MaskShape *shape = (MaskShape *)value.data; + + BKE_mask_shape_active_set(mask, shape); +} + +static void rna_MaskShape_splines_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + MaskShape *shape = (MaskShape *)ptr->data; + + rna_iterator_listbase_begin(iter, &shape->splines, NULL); +} + +void rna_MaskShape_name_set(PointerRNA *ptr, const char *value) +{ + Mask *mask = (Mask *)ptr->id.data; + MaskShape *shape = (MaskShape *)ptr->data; + + BLI_strncpy(shape->name, value, sizeof(shape->name)); + + BKE_mask_shape_unique_name(mask, shape); +} + +static PointerRNA rna_MaskShape_active_spline_get(PointerRNA *ptr) +{ + MaskShape *shape = (MaskShape *)ptr->data; + + return rna_pointer_inherit_refine(ptr, &RNA_MaskSpline, shape->act_spline); +} + +static void rna_MaskShape_active_spline_set(PointerRNA *ptr, PointerRNA value) +{ + MaskShape *shape = (MaskShape *)ptr->data; + MaskSpline *spline = (MaskSpline *)value.data; + int index = BLI_findindex(&shape->splines, spline); + + if (index >= 0) + shape->act_spline = spline; + else + shape->act_spline = NULL; +} + +static PointerRNA rna_MaskShape_active_spline_point_get(PointerRNA *ptr) +{ + MaskShape *shape = (MaskShape *)ptr->data; + + return rna_pointer_inherit_refine(ptr, &RNA_MaskSplinePoint, shape->act_point); +} + +static void rna_MaskShape_active_spline_point_set(PointerRNA *ptr, PointerRNA value) +{ + MaskShape *shape = (MaskShape *)ptr->data; + MaskSpline *spline = shape->splines.first; + MaskSplinePoint *point = (MaskSplinePoint *)value.data; + + shape->act_point = NULL; + + while (spline) { + if (point >= spline->points && point < spline->points + spline->tot_point) { + shape->act_point = point; + + break; + } + + spline = spline->next; + } +} + +static void rna_MaskSplinePoint_handle1_get(PointerRNA *ptr, float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + values[0] = bezt->vec[0][0]; + values[1] = bezt->vec[0][1]; + values[2] = bezt->vec[0][2]; +} + +static void rna_MaskSplinePoint_handle1_set(PointerRNA *ptr, const float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + bezt->vec[0][0] = values[0]; + bezt->vec[0][1] = values[1]; + bezt->vec[0][2] = values[2]; +} + +static void rna_MaskSplinePoint_handle2_get(PointerRNA *ptr, float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + values[0] = bezt->vec[2][0]; + values[1] = bezt->vec[2][1]; + values[2] = bezt->vec[2][2]; +} + +static void rna_MaskSplinePoint_handle2_set(PointerRNA *ptr, const float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + bezt->vec[2][0] = values[0]; + bezt->vec[2][1] = values[1]; + bezt->vec[2][2] = values[2]; +} + +static void rna_MaskSplinePoint_ctrlpoint_get(PointerRNA *ptr, float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + values[0] = bezt->vec[1][0]; + values[1] = bezt->vec[1][1]; + values[2] = bezt->vec[1][2]; +} + +static void rna_MaskSplinePoint_ctrlpoint_set(PointerRNA *ptr, const float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + bezt->vec[1][0] = values[0]; + bezt->vec[1][1] = values[1]; + bezt->vec[1][2] = values[2]; +} + +static int rna_MaskSplinePoint_handle_type_get(PointerRNA *ptr) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + return bezt->h1; +} + +static void rna_MaskSplinePoint_handle_type_set(PointerRNA *ptr, int value) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + bezt->h1 = bezt->h2 = value; +} + +/* ** API ** */ + +static MaskShape *rna_Mask_shape_new(Mask *mask, const char *name) +{ + MaskShape *shape = BKE_mask_shape_new(mask, name); + + WM_main_add_notifier(NC_MASK|NA_EDITED, mask); + + return shape; +} + +void rna_Mask_shape_remove(Mask *mask, MaskShape *shape) +{ + BKE_mask_shape_remove(mask, shape); + + WM_main_add_notifier(NC_MASK|NA_EDITED, mask); +} + +static void rna_MaskShape_spline_add(ID *id, MaskShape *shape, int number) +{ + Mask *mask = (Mask*) id; + int i; + + for (i = 0; i < number; i++) + BKE_mask_spline_add(shape); + + WM_main_add_notifier(NC_MASK|NA_EDITED, mask); +} + +#else + +static void rna_def_maskParent(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem mask_id_type_items[] = { + {ID_MC, "MOVIECLIP", ICON_SEQUENCE, "Movie Clip", ""}, + {0, NULL, 0, NULL, NULL}}; + + srna = RNA_def_struct(brna, "MaskParent", NULL); + RNA_def_struct_ui_text(srna, "Mask Parent", "Parenting settings for maskign element"); + + /* use_parent */ + prop = RNA_def_property(srna, "use_parent", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_PARENT_ACTIVE); + RNA_def_property_ui_text(prop, "Use Parent", "Use parenting for this object"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* Target Properties - ID-block to Drive */ + prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ID"); + RNA_def_property_flag(prop, PROP_EDITABLE); + // RNA_def_property_editable_func(prop, "rna_maskSpline_id_editable"); + /* note: custom set function is ONLY to avoid rna setting a user for this. */ + RNA_def_property_pointer_funcs(prop, NULL, "rna_MaskParent_id_set", "rna_MaskParent_id_typef", NULL); + RNA_def_property_ui_text(prop, "ID", "ID-block to which masking element would be parented to or to it's property"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + prop = RNA_def_property(srna, "id_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "id_type"); + RNA_def_property_enum_items(prop, mask_id_type_items); + RNA_def_property_enum_default(prop, ID_MC); + RNA_def_property_enum_funcs(prop, NULL, "rna_MaskParent_id_type_set", NULL); + //RNA_def_property_editable_func(prop, "rna_MaskParent_id_type_editable"); + RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* parent */ + prop = RNA_def_property(srna, "parent", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Parent", "Name of parent object in specified data block to which parenting happens"); + RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* sub_parent */ + prop = RNA_def_property(srna, "sub_parent", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Sub Parent", "Name of parent sub-object in specified data block to which parenting happens"); + RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); +} + +static void rna_def_maskSplinePointUW(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MaskSplinePointUW", NULL); + RNA_def_struct_ui_text(srna, "Mask Spline UW Point", "Single point in spline segment defining feather"); + + /* u */ + prop = RNA_def_property(srna, "u", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "u"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "U", "U coordinate of point along spline segment"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* weight */ + prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "w"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "Weight", "Weight of feather point"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* select */ + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); + RNA_def_property_ui_text(prop, "Select", "Selection status"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); +} + +static void rna_def_maskSplinePoint(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem handle_type_items[] = { + {HD_AUTO, "AUTO", 0, "Auto", ""}, + {HD_VECT, "VECTOR", 0, "Vector", ""}, + {HD_ALIGN, "ALIGNED", 0, "Aligned", ""}, + {0, NULL, 0, NULL, NULL}}; + + rna_def_maskSplinePointUW(brna); + + srna = RNA_def_struct(brna, "MaskSplinePoint", NULL); + RNA_def_struct_ui_text(srna, "Mask Spline Point", "Single point in spline used for defining mash shape"); + + /* Vector values */ + prop = RNA_def_property(srna, "handle_left", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 3); + RNA_def_property_float_funcs(prop, "rna_MaskSplinePoint_handle1_get", "rna_MaskSplinePoint_handle1_set", NULL); + RNA_def_property_ui_text(prop, "Handle 1", "Coordinates of the first handle"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 3); + RNA_def_property_float_funcs(prop, "rna_MaskSplinePoint_ctrlpoint_get", "rna_MaskSplinePoint_ctrlpoint_set", NULL); + RNA_def_property_ui_text(prop, "Control Point", "Coordinates of the control point"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + prop = RNA_def_property(srna, "handle_right", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 3); + RNA_def_property_float_funcs(prop, "rna_MaskSplinePoint_handle2_get", "rna_MaskSplinePoint_handle2_set", NULL); + RNA_def_property_ui_text(prop, "Handle 2", "Coordinates of the second handle"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* handle_type */ + prop = RNA_def_property(srna, "handle_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_funcs(prop, "rna_MaskSplinePoint_handle_type_get", "rna_MaskSplinePoint_handle_type_set", NULL); + RNA_def_property_enum_items(prop, handle_type_items); + RNA_def_property_ui_text(prop, "Handle Type", "Handle type"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* select */ + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "bezt.f1", SELECT); + RNA_def_property_ui_text(prop, "Select", "Selection status"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* parent */ + prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskParent"); + + /* feather points */ + prop = RNA_def_property(srna, "feather_points", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskSplinePointUW"); + RNA_def_property_collection_sdna(prop, NULL, "uw", "tot_uw"); + RNA_def_property_ui_text(prop, "Feather Points", "Points defining feather"); +} + +static void rna_def_maskSplines(BlenderRNA *brna) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MaskSplines", NULL); + RNA_def_struct_sdna(srna, "MaskShape"); + RNA_def_struct_ui_text(srna, "Mask Splines", "Collection of masking splines"); + + func = RNA_def_function(srna, "add", "rna_MaskShape_spline_add"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_ui_description(func, "Add a number of splines to mask shape"); + RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of splines to add to the shape", 0, INT_MAX); + + /* active spline */ + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskSpline"); + RNA_def_property_pointer_funcs(prop, "rna_MaskShape_active_spline_get", "rna_MaskShape_active_spline_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking shape"); + + /* active point */ + prop = RNA_def_property(srna, "active_point", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskSplinePoint"); + RNA_def_property_pointer_funcs(prop, "rna_MaskShape_active_spline_point_get", "rna_MaskShape_active_spline_point_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking shape"); +} + +static void rna_def_maskSpline(BlenderRNA *brna) +{ + static EnumPropertyItem spline_interpolation_items[] = { + {MASK_SPLINE_INTERP_LINEAR, "LINEAR", 0, "Linear", ""}, + {MASK_SPLINE_INTERP_EASE, "EASE", 0, "Ease", ""}, + {0, NULL, 0, NULL, NULL}}; + + StructRNA *srna; + PropertyRNA *prop; + + rna_def_maskSplinePoint(brna); + + srna = RNA_def_struct(brna, "MaskSpline", NULL); + RNA_def_struct_ui_text(srna, "Mask spline", "Single spline used for defining mash shape"); + + /* weight interpolation */ + prop = RNA_def_property(srna, "weight_interpolation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "weight_interp"); + RNA_def_property_enum_items(prop, spline_interpolation_items); + RNA_def_property_ui_text(prop, "Weight Interpolation", "The type of weight interpolation for spline"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* cyclic */ + prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_SPLINE_CYCLIC); + RNA_def_property_ui_text(prop, "Cyclic", "Make this spline a closed loop"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); +} + +static void rna_def_maskShape(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + rna_def_maskSpline(brna); + rna_def_maskSplines(brna); + + srna = RNA_def_struct(brna, "MaskShape", NULL); + RNA_def_struct_ui_text(srna, "Mask shape", "Single shape used for masking stuff"); + + /* name */ + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Unique name of shape"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MaskShape_name_set"); + RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + RNA_def_struct_name_property(srna, prop); + + /* splines */ + prop = RNA_def_property(srna, "splines", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_MaskShape_splines_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_struct_type(prop, "MaskSpline"); + RNA_def_property_ui_text(prop, "Splines", "Collection of splines which defines this shape"); + RNA_def_property_srna(prop, "MaskSplines"); +} + +static void rna_def_maskShapes(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MaskShapes"); + srna = RNA_def_struct(brna, "MaskShapes", NULL); + RNA_def_struct_sdna(srna, "Mask"); + RNA_def_struct_ui_text(srna, "Mask Shapes", "Collection of shapes used by mask"); + + func = RNA_def_function(srna, "new", "rna_Mask_shape_new"); + RNA_def_function_ui_description(func, "Add shape to this mask"); + RNA_def_string(func, "name", "", 0, "Name", "Name of new shape"); + parm = RNA_def_pointer(func, "shape", "MaskShape", "", "New mask shape"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_Mask_shape_remove"); + RNA_def_function_ui_description(func, "Remove shape from this mask"); + RNA_def_pointer(func, "shape", "MaskShape", "", "Shape to be removed"); + + /* active object */ + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskShape"); + RNA_def_property_pointer_funcs(prop, "rna_Mask_active_shape_get", "rna_Mask_active_shape_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Shape", "Active shape in this mask"); +} + +static void rna_def_mask(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + rna_def_maskShape(brna); + + srna = RNA_def_struct(brna, "Mask", "ID"); + RNA_def_struct_ui_text(srna, "Mask", "Mask datablock defining mask for compositing"); + RNA_def_struct_ui_icon(srna, ICON_MOD_MASK); + + /* shapes */ + prop = RNA_def_property(srna, "shapes", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_Mask_shapes_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_struct_type(prop, "MaskShape"); + RNA_def_property_ui_text(prop, "Shapes", "Collection of shapes which defines this mask"); + rna_def_maskShapes(brna, prop); + + /* active shape index */ + prop = RNA_def_property(srna, "active_shape_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "shapenr"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_int_funcs(prop, "rna_Mask_active_shape_index_get", "rna_Mask_active_shape_index_set", "rna_Mask_active_shape_index_range"); + RNA_def_property_ui_text(prop, "Active Shape Index", "Index of active shape in list of all mask's shapes"); +} + +void RNA_def_mask(BlenderRNA *brna) +{ + rna_def_maskParent(brna); + rna_def_mask(brna); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 58fd936819b..a6c3c664ce6 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2875,6 +2875,18 @@ static void def_cmp_moviedistortion(StructRNA *srna) RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); } +static void def_cmp_mask(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_struct_type(prop, "Mask"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Mask", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); +} + static void dev_cmd_transform(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index 5352bbd0e0f..e536314e145 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -158,6 +158,7 @@ DefNode( CompositorNode, CMP_NODE_MOVIECLIP, def_cmp_movieclip, "MOVIE DefNode( CompositorNode, CMP_NODE_TRANSFORM, dev_cmd_transform, "TRANSFORM", Transform, "Transform", "" ) DefNode( CompositorNode, CMP_NODE_STABILIZE2D, def_cmp_stabilize2d, "STABILIZE2D", Stabilize, "Stabilize 2D", "" ) DefNode( CompositorNode, CMP_NODE_MOVIEDISTORTION,def_cmp_moviedistortion,"MOVIEDISTORTION",MovieDistortion, "Movie Distortion", "" ) +DefNode( CompositorNode, CMP_NODE_MASK, def_cmp_mask, "MASK", Mask, "Mask", "" ) DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" ) DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" ) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 47bad8f31e5..532690eff64 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -115,6 +115,7 @@ EnumPropertyItem viewport_shade_items[] = { #ifdef RNA_RUNTIME #include "DNA_anim_types.h" +#include "DNA_mask_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -1029,6 +1030,13 @@ static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, PointerRNA value) ED_space_clip_set(NULL, screen, sc, (MovieClip*)value.data); } +static void rna_SpaceClipEditor_mask_set(PointerRNA *ptr, PointerRNA value) +{ + SpaceClip *sc= (SpaceClip*)(ptr->data); + + ED_space_clip_set_mask(NULL, sc, (Mask*)value.data); +} + static void rna_SpaceClipEditor_clip_mode_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { SpaceClip *sc = (SpaceClip*)(ptr->data); @@ -2926,6 +2934,7 @@ static void rna_def_space_clip(BlenderRNA *brna) {SC_MODE_RECONSTRUCTION, "RECONSTRUCTION", ICON_SNAP_FACE, "Reconstruction", "Show tracking/reconstruction tools"}, {SC_MODE_DISTORTION, "DISTORTION", ICON_GRID, "Distortion", "Show distortion tools"}, + {SC_MODE_MASKEDITING, "MASKEDITING", ICON_MOD_MASK, "Mask editing", "Show mask editing tools"}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem view_items[] = { @@ -2954,6 +2963,13 @@ static void rna_def_space_clip(BlenderRNA *brna) "Parameters defining which frame of the movie clip is displayed"); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + /* mask */ + prop= RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Mask", "Mask displayed and edited in this space"); + RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceClipEditor_mask_set", NULL, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + /* mode */ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 9bcbc91265c..5320d9f65cc 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -35,6 +35,7 @@ set(INC ../makesrna ../render/extern/include ../../../intern/guardedalloc + ../../../intern/raskter ) set(INC_SYS @@ -81,6 +82,7 @@ set(SRC composite/nodes/node_composite_mapUV.c composite/nodes/node_composite_mapValue.c composite/nodes/node_composite_math.c + composite/nodes/node_composite_mask.c composite/nodes/node_composite_mixrgb.c composite/nodes/node_composite_movieclip.c composite/nodes/node_composite_moviedistortion.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 284b89bc095..4378c6a1d36 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -50,6 +50,7 @@ void register_node_type_cmp_value(struct bNodeTreeType *ttype); void register_node_type_cmp_rgb(struct bNodeTreeType *ttype); void register_node_type_cmp_curve_time(struct bNodeTreeType *ttype); void register_node_type_cmp_movieclip(struct bNodeTreeType *ttype); +void register_node_type_cmp_usermask(struct bNodeTreeType *ttype); void register_node_type_cmp_composite(struct bNodeTreeType *ttype); void register_node_type_cmp_viewer(struct bNodeTreeType *ttype); @@ -115,6 +116,7 @@ void register_node_type_cmp_mapuv(struct bNodeTreeType *ttype); void register_node_type_cmp_transform(struct bNodeTreeType *ttype); void register_node_type_cmp_stabilize2d(struct bNodeTreeType *ttype); void register_node_type_cmp_moviedistortion(struct bNodeTreeType *ttype); +void register_node_type_cmp_mask(struct bNodeTreeType *ttype); void register_node_type_cmp_glare(struct bNodeTreeType *ttype); void register_node_type_cmp_tonemap(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 049b5dd8178..ca8922eaf64 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -872,6 +872,10 @@ int ntreeCompositTagAnimated(bNodeTree *ntree) nodeUpdate(ntree, node); tagged= 1; } + else if (node->type==CMP_NODE_MASK) { + nodeUpdate(ntree, node); + tagged= 1; + } } return tagged; diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c new file mode 100644 index 00000000000..2c49be48f7d --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -0,0 +1,124 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_mask.c + * \ingroup cmpnodes + */ + +#include "BLF_translation.h" + +#include "DNA_mask_types.h" + +#include "BKE_mask.h" + +// XXX: ... +#include "../../../../intern/raskter/raskter.h" +#include "node_composite_util.h" + +/* **************** Translate ******************** */ + +static bNodeSocketTemplate cmp_node_mask_in[] = { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate cmp_node_mask_out[] = { + { SOCK_RGBA, 0, "Image"}, + { -1, 0, "" } +}; + +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + if (node->id) { + Mask *mask = (Mask *)node->id; + CompBuf *stackbuf; + RenderData *rd = data; + MaskShape *shape = mask->shapes.first; + float *res; + int sx, sy; + + if (!out[0]->hasoutput) { + /* the node's output socket is not connected to anything... + * do not execute any further, just exit the node immediately + */ + return; + } + + if (in[0]->hasinput && in[0]->data) { + CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA); + + sx = cbuf->x; + sy = cbuf->y; + } + else { + sx = (rd->size * rd->xsch) / 100; + sy = (rd->size * rd->ysch) / 100; + } + + /* allocate the output buffer */ + stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE); + res = stackbuf->rect; + + shape = mask->shapes.first; + while (shape) { + MaskSpline *spline = shape->splines.first; + + while (spline) { + float *diff_points; + int tot_diff_point; + + diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); + + if (tot_diff_point) { + PLX_raskterize(diff_points, tot_diff_point, res, sx, sy); + + MEM_freeN(diff_points); + } + + spline = spline->next; + } + + shape = shape->next; + } + + /* pass on output and free */ + out[0]->data = stackbuf; + } +} + +void register_node_type_cmp_mask(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_MASK, "Mask", NODE_CLASS_INPUT, NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_mask_in, cmp_node_mask_out); + node_type_size(&ntype, 140, 100, 320); + node_type_exec(&ntype, exec); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 7cbeab6a02e..25abc171057 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -167,6 +167,7 @@ typedef struct wmNotifier { #define NC_ID (18<<24) #define NC_LOGIC (19<<24) #define NC_MOVIECLIP (20<<24) +#define NC_MASK (21<<24) /* data type, 256 entries is enough, it can overlap */ #define NOTE_DATA 0x00FF0000 diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 7edf5314821..70354c0a2ec 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -154,6 +154,7 @@ endif() bf_blenkernel # duplicate for linking bf_intern_mikktspace extern_recastnavigation + bf_intern_raskter ) if(WITH_MOD_CLOTH_ELTOPO) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index a036e8a8212..ad9bd924e9f 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -236,6 +236,7 @@ void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSett void ED_screen_set_scene(struct bContext *C, struct Scene *scene){} void ED_space_clip_set(struct bContext *C, struct SpaceClip *sc, struct MovieClip *clip){} +void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask){} void ED_area_tag_redraw_regiontype(struct ScrArea *sa, int regiontype){} void ED_render_engine_changed(struct Main *bmain) {} diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 0168c06b7da..f81d6320c23 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -807,6 +807,7 @@ endif() bf_editor_sound bf_editor_animation bf_editor_datafiles + bf_editor_mask bf_render bf_intern_opennl @@ -877,6 +878,7 @@ endif() cycles_kernel cycles_util cycles_subd + bf_intern_raskter ) if(WITH_LIBMV) From 288a734b6ff0ece0264e1f623130368eb1e6f3b3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Apr 2012 10:04:20 +0000 Subject: [PATCH 024/183] Tomato: disable texture buffers for intel cards due to they're constantly blinking with black frames Also remove unused code. --- .../blender/editors/space_clip/clip_editor.c | 36 ++++--------------- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 2e7de318299..cd3d04279ac 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -486,7 +486,12 @@ int ED_space_clip_texture_buffer_supported(SpaceClip *sc) if (!context->support_checked) { context->support_checked = TRUE; - context->buffers_supported = GPU_non_power_of_two_support(); + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { + context->buffers_supported = FALSE; + } + else { + context->buffers_supported = GPU_non_power_of_two_support(); + } } return context->buffers_supported; @@ -526,35 +531,6 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) context->texture_allocated = 0; } -#if 0 - /* disabled for now because current tracking users have got NPOT textures - * working smoothly on their computers and forcing re-scaling during playback - * slows down playback a lot */ - - /* if videocard doesn't support NPOT textures, need to do rescaling */ - if (!GPU_non_power_of_two_support()) { - if (!is_power_of_2_i(width) || !is_power_of_2_i(height)) { - width = power_of_2_max_i(width); - height = power_of_2_max_i(height); - - if (ibuf->x != width || ibuf->y != height) { - if (frect) { - fscalerect= MEM_mallocN(width*width*sizeof(*fscalerect)*4, "fscalerect"); - gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float, width, height, GL_FLOAT, fscalerect); - - frect = fscalerect; - } - else { - scalerect= MEM_mallocN(width*height*sizeof(*scalerect), "scalerect"); - gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect, width, height, GL_UNSIGNED_BYTE, scalerect); - - rect = scalerect; - } - } - } - } -#endif - if (need_recreate || !context->texture_allocated) { /* texture doesn't exist yet or need to be re-allocated because of changed dimensions */ int filter = GL_LINEAR; From 0974368b322ac06b41c90c1dfd87a2df91f324b9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Apr 2012 11:31:22 +0000 Subject: [PATCH 025/183] Tomato: versioning patch for current files which have got curves view open --- source/blender/blenloader/intern/readfile.c | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 753cd93b89a..a46d05fc97c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -13389,6 +13389,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + { + bScreen *sc; + + for (sc = main->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sclip = (SpaceClip *)sl; + ARegion *ar; + int hide = FALSE; + + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_PREVIEW) { + if (ar->alignment != RGN_ALIGN_NONE) { + ar->flag |= RGN_FLAG_HIDDEN; + ar->v2d.flag &= ~V2D_IS_INITIALISED; + ar->alignment = RGN_ALIGN_NONE; + + hide = TRUE; + } + } + } + + if (hide) { + sclip->view = SC_VIEW_CLIP; + } + } + } + } + } + } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ From 398884d1866fc3d9aa95892c534498a27cef9491 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 3 May 2012 07:32:26 +0000 Subject: [PATCH 026/183] Tomato: update raskter library to newer version from Pete Larbell --- intern/raskter/raskter.c | 109 ++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 35 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index d5890f1741a..0839e8a09c2 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -31,7 +31,10 @@ #include #include "raskter.h" -#define R_XCHG(a,b) t=a;a=b;b=t; +// from BLI_utildefines.h +#define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) +#define MAX2(x,y) ( (x)>(y) ? (x) : (y) ) + struct e_status { int x; @@ -69,7 +72,7 @@ static void preprocess_all_edges(struct poly_vert * verts, int num_verts, struct int yend; int dx; int dy; - int t; + int temp_pos; int xdist; struct e_status *e_new; struct e_status *next_edge; @@ -80,36 +83,58 @@ static void preprocess_all_edges(struct poly_vert * verts, int num_verts, struct all_edges = NULL; // loop all verts for(i = 0; i < num_verts; i++) { + // determine beginnings and endings of edges, linking last vertex to first vertex xbeg = v[i].x; ybeg = v[i].y; - // determine starts and ends of edges, linking last vertex to first vertex - if(i == 0) { - xend = v[num_verts-1].x; - yend = v[num_verts-1].y; - } else { + if(i) { + // we're not at the last vert, so end of the edge is the previous vertex xend = v[i-1].x; yend = v[i-1].y; + } else { + // we're at the first vertex, so the "end" of this edge is the last vertex + xend = v[num_verts-1].x; + yend = v[num_verts-1].y; } // make sure our edges are facing the correct direction if(ybeg > yend) { - R_XCHG(xbeg, xend); - R_XCHG(ybeg, yend); + // flip the Xs + temp_pos = xbeg; + xbeg = xend; + xend = temp_pos; + // flip the Ys + temp_pos = ybeg; + ybeg = yend; + yend = temp_pos; } - // create the edge and determine it's slope (for incremental line drawing) - if((dy = yend - ybeg) != 0) { + + // calculate y delta + dy = yend - ybeg; + // dont draw horizontal lines directly, they are scanned as part of the edges they connect, so skip em. :) + if(dy) { + // create the edge and determine it's slope (for incremental line drawing) e_new = open_edge++; - e_new->xdir = ((dx = xend - xbeg) > 0) ? 1 : -1; - xdist = (dx > 0) ? dx : -dx; + + // calculate x delta + dx = xend - xbeg; + if(dx > 0){ + e_new->xdir = 1; + xdist = dx; + }else{ + e_new->xdir = -1; + xdist = -dx; + } + e_new->x = xbeg; e_new->ybeg = ybeg; e_new->num = dy; e_new->drift_dec = dy; + + // calculate deltas for incremental drawing if(dx >= 0) { e_new->drift = 0; } else { e_new->drift = -dy + 1; } - // calculate deltas for drawing if(dy >= xdist) { e_new->drift_inc = xdist; e_new->xshift = 0; @@ -121,7 +146,7 @@ static void preprocess_all_edges(struct poly_vert * verts, int num_verts, struct // link in all the edges, in sorted order for(;;) { next_edge = *next_edge_ref; - if((next_edge == NULL) || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) { + if(!next_edge || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) { e_new->e_next = next_edge; *next_edge_ref = e_new; break; @@ -197,7 +222,7 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. Will get changed once DEM code gets in. */ - for(y_curr = (all_edges->ybeg > 0 ? all_edges->ybeg : 0); ((all_edges != NULL) || (possible_edges != NULL)) && (y_curr < rb.sizey); y_curr++) { + for(y_curr = MAX2(all_edges->ybeg,0); (all_edges || possible_edges) && (y_curr < rb.sizey); y_curr++) { /* Link any edges that start on the current scan line into the list of @@ -214,19 +239,19 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { At each iteration, make sure we still have a non-NULL edge. */ - for(edgec = &possible_edges; (all_edges != NULL) && (all_edges->ybeg == y_curr);) { + for(edgec = &possible_edges; all_edges && (all_edges->ybeg == y_curr);) { x_curr = all_edges->x; // Set current X position. - for(;;) { // Start looping edges. Will break when edges run out. - e_curr = *edgec; // Set up a current edge pointer. - if((e_curr == NULL) || (e_curr->x >= x_curr)) { // If we have an no edge, or we need to skip some X-span, + for(;;) { // Start looping edges. Will break when edges run out. + e_curr = *edgec; // Set up a current edge pointer. + if(!e_curr || (e_curr->x >= x_curr)) { // If we have an no edge, or we need to skip some X-span, e_temp = all_edges->e_next; // set a temp "next" edge to test. *edgec = all_edges; // Add this edge to the list to be scanned. all_edges->e_next = e_curr; // Set up the next edge. edgec = &all_edges->e_next; // Set our list to the next edge's location in memory. all_edges = e_temp; // Skip the NULL or bad X edge, set pointer to next edge. - break; // Stop looping edges (since we ran out or hit empty X span. + break; // Stop looping edges (since we ran out or hit empty X span. } else { - edgec = &e_curr->e_next; // Set the pointer to the edge list the "next" edge. + edgec = &e_curr->e_next; // Set the pointer to the edge list the "next" edge. } } } @@ -248,7 +273,7 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge we will eventually hit a NULL when the list runs out. */ - for(e_curr = possible_edges; e_curr != NULL; e_curr = e_curr->e_next) { + for(e_curr = possible_edges; e_curr; e_curr = e_curr->e_next) { /* Calculate a span of pixels to fill on the current scan line. @@ -263,9 +288,12 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, but for now it is done here until the DEM code comes in. */ - cpxl = spxl + (e_curr->x > 0 ? e_curr->x : 0); + // set up xmin and xmax bounds on this scan line + cpxl = spxl + MAX2(e_curr->x,0); e_curr = e_curr->e_next; - mpxl = spxl + (e_curr->x < rb.sizex ? e_curr->x : rb.sizex) - 1; + mpxl = spxl + MIN2(e_curr->x,rb.sizex) - 1; + + // draw the pixels. for(; cpxl <= mpxl; *cpxl++ = 1.0f); } @@ -278,8 +306,8 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { polygons, we dont have fractional positions, so we only move in x-direction when needed to get all the way to the next pixel over... */ - for(edgec = &possible_edges; (e_curr = *edgec) != NULL;) { - if((--(e_curr->num)) == 0) { + for(edgec = &possible_edges; (e_curr = *edgec);) { + if(!(--(e_curr->num))) { *edgec = e_curr->e_next; } else { e_curr->x += e_curr->xshift; @@ -298,28 +326,38 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { pass, then we know we need to sort by x, so then cycle through edges again and perform the sort.- */ - if(possible_edges != NULL) { - for(edgec = &possible_edges; (e_curr = *edgec)->e_next != NULL;) { + if(possible_edges) { + for(edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + // if the current edge hits scan line at greater X than the next edge, we need to exchange the edges if(e_curr->x > e_curr->e_next->x) { - e_temp = e_curr->e_next->e_next; *edgec = e_curr->e_next; + // exchange the pointers + e_temp = e_curr->e_next->e_next; e_curr->e_next->e_next = e_curr; e_curr->e_next = e_temp; + // set flag that we had at least one switch swixd = 1; } - edgec = &(*edgec)->e_next; } - for(; swixd;) { + // if we did have a switch, look for more (there will more if there was one) + for(;;) { + // reset exchange flag so it's only set if we encounter another one swixd = 0; - for(edgec = &possible_edges; (e_curr = *edgec)->e_next != NULL;) { + for(edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + // again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag if(e_curr->x > e_curr->e_next->x) { - e_temp = e_curr->e_next->e_next; *edgec = e_curr->e_next; + // exchange the pointers + e_temp = e_curr->e_next->e_next; e_curr->e_next->e_next = e_curr; e_curr->e_next = e_temp; + // flip the exchanged flag swixd = 1; } - edgec = &(*edgec)->e_next; + } + // if we had no exchanges, we're done reshuffling the pointers + if(!swixd) { + break; } } } @@ -365,3 +403,4 @@ int PLX_raskterize(float * verts, int num, float * buf, int buf_x, int buf_y) { free(ply); // Free the memory allocated for the integer coordinate table. return(i); // Return the value returned by the rasterizer. } + From 5b7cad343e7e5cd09a9dbc6fb973d04c9d11ba3e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 9 May 2012 15:39:54 +0000 Subject: [PATCH 027/183] Initial Ceres integration into Blender Currently only put sources of Ceres library into extern/libmv/third_party and setup CMake and SCons building systems. Integration details: - Even CMake build files are not re-used from Ceres's trunk: they're using some automatic stuff detection like glog, pthreads, protobuf and so and it's not so clear how to re-use that files without modifications. And IMO it's easier if build files are getting re-generated automatically to match Blender-specific setup rather than keeping changes made locally in Blender in sync when re-bundling Ceres library. Especially in case when it's alerady needed to support SCons build system. - Integrated only actual sources, all tests were stripped. Probably it'll be nice to have them, but they'll need clear integration with current module test stuff in Blender. Hopefully integration went smooth. - Suitesparse was disabled. It'll help a lot having it, but there are some difficulties making cholmod working fine on windows. Would be added in future - collections_port.cc was also stripped. It's not used by Ceres's upstream and it gives compilation error (undefined uint32 -- looks like namespace issue). - Currently all schur eliminators are included. Not sure if it makes sense, also not sure if it makes sense having them switchable on and off -- IMO better to have single configuration which works and does not require special tweaks after everything was set up. - Personally i'd say if some of Ceres modules are not used better to drop it away -- all symbols would be stripped anyway, but it'll be waste of compilation time which is annoying in cases when one doing, say, binary search of revision at which some regression was introduced. Especially when it's easy to add modules which should be used by Blender. But as long as it stays in Tomato i'm not worrying much about this. To bundle updated version of Ceres: - You'll need to use GIT-SVN checkout, Re-bundling Ceres using SVN is still NOT supported! - Go to extern/libmv/third_party/ceres folder - Run ./bundle.sh This will checkout fresh Ceres snapshot of Windows branch (which is currently most interesting from integration into Blender POV), apply all patches listed in patches/series and copy needed files into Blender's working copy. This will also re-generate CMake/SCons build rules. If you'll need extra files from Ceres repository which are not present in Blender, you'll need to copy them manually and then run ./mkfiles.sh from extern/libmv/third_party/ceres folder which will update list of files used by Blender. Thanks all Ceres developers for this library and thanks to Keir Mierle with help integrating Ceres into Blender! --- extern/libmv/CMakeLists.txt | 3 + extern/libmv/ChangeLog | 81 +- extern/libmv/SConscript | 4 +- extern/libmv/bundle.sh | 15 +- extern/libmv/libmv/image/convolve.cc | 14 + extern/libmv/libmv/image/convolve.h | 10 + extern/libmv/mkfiles.sh | 2 +- extern/libmv/third_party/CMakeLists.txt | 2 + extern/libmv/third_party/SConscript | 3 + extern/libmv/third_party/ceres/CMakeLists.txt | 218 ++++++ extern/libmv/third_party/ceres/ChangeLog | 227 ++++++ extern/libmv/third_party/ceres/LICENSE | 27 + extern/libmv/third_party/ceres/README | 3 + extern/libmv/third_party/ceres/SConscript | 34 + extern/libmv/third_party/ceres/bundle.sh | 183 +++++ extern/libmv/third_party/ceres/files.txt | 150 ++++ .../include/ceres/autodiff_cost_function.h | 170 +++++ .../third_party/ceres/include/ceres/ceres.h | 48 ++ .../include/ceres/conditioned_cost_function.h | 97 +++ .../ceres/include/ceres/cost_function.h | 127 ++++ .../ceres/include/ceres/internal/autodiff.h | 374 ++++++++++ .../ceres/include/ceres/internal/eigen.h | 80 ++ .../include/ceres/internal/fixed_array.h | 193 +++++ .../ceres/include/ceres/internal/macros.h | 154 ++++ .../ceres/internal/manual_constructor.h | 214 ++++++ .../ceres/include/ceres/internal/port.h | 44 ++ .../ceres/include/ceres/internal/scoped_ptr.h | 311 ++++++++ .../ceres/include/ceres/iteration_callback.h | 159 ++++ .../third_party/ceres/include/ceres/jet.h | 671 +++++++++++++++++ .../include/ceres/local_parameterization.h | 189 +++++ .../ceres/include/ceres/loss_function.h | 322 ++++++++ .../ceres/include/ceres/normal_prior.h | 75 ++ .../ceres/numeric_diff_cost_function.h | 283 +++++++ .../third_party/ceres/include/ceres/problem.h | 265 +++++++ .../ceres/include/ceres/rotation.h | 526 +++++++++++++ .../ceres/include/ceres/sized_cost_function.h | 82 ++ .../third_party/ceres/include/ceres/solver.h | 379 ++++++++++ .../third_party/ceres/include/ceres/types.h | 224 ++++++ .../internal/ceres/block_evaluate_preparer.cc | 73 ++ .../internal/ceres/block_evaluate_preparer.h | 67 ++ .../ceres/block_jacobi_preconditioner.cc | 136 ++++ .../ceres/block_jacobi_preconditioner.h | 84 +++ .../internal/ceres/block_jacobian_writer.cc | 209 ++++++ .../internal/ceres/block_jacobian_writer.h | 127 ++++ .../ceres/block_random_access_dense_matrix.cc | 83 +++ .../ceres/block_random_access_dense_matrix.h | 98 +++ .../ceres/block_random_access_matrix.cc | 40 + .../ceres/block_random_access_matrix.h | 132 ++++ .../block_random_access_sparse_matrix.cc | 158 ++++ .../ceres/block_random_access_sparse_matrix.h | 109 +++ .../internal/ceres/block_sparse_matrix.cc | 263 +++++++ .../internal/ceres/block_sparse_matrix.h | 142 ++++ .../ceres/internal/ceres/block_structure.cc | 92 +++ .../ceres/internal/ceres/block_structure.h | 105 +++ .../ceres/canonical_views_clustering.cc | 238 ++++++ .../ceres/canonical_views_clustering.h | 133 ++++ .../third_party/ceres/internal/ceres/casts.h | 108 +++ .../internal/ceres/cgnr_linear_operator.h | 120 +++ .../ceres/internal/ceres/cgnr_solver.cc | 80 ++ .../ceres/internal/ceres/cgnr_solver.h | 66 ++ .../ceres/internal/ceres/collections_port.h | 141 ++++ .../ceres/compressed_row_jacobian_writer.cc | 201 +++++ .../ceres/compressed_row_jacobian_writer.h | 75 ++ .../ceres/compressed_row_sparse_matrix.cc | 325 ++++++++ .../ceres/compressed_row_sparse_matrix.h | 129 ++++ .../ceres/conditioned_cost_function.cc | 130 ++++ .../ceres/conjugate_gradients_solver.cc | 233 ++++++ .../ceres/conjugate_gradients_solver.h | 74 ++ .../ceres/internal/ceres/corrector.cc | 125 ++++ .../ceres/internal/ceres/corrector.h | 88 +++ .../internal/ceres/dense_jacobian_writer.h | 110 +++ .../ceres/internal/ceres/dense_qr_solver.cc | 93 +++ .../ceres/internal/ceres/dense_qr_solver.h | 99 +++ .../internal/ceres/dense_sparse_matrix.cc | 184 +++++ .../internal/ceres/dense_sparse_matrix.h | 115 +++ .../ceres/internal/ceres/detect_structure.cc | 114 +++ .../ceres/internal/ceres/detect_structure.h | 63 ++ .../ceres/internal/ceres/evaluator.cc | 71 ++ .../ceres/internal/ceres/evaluator.h | 129 ++++ .../third_party/ceres/internal/ceres/file.cc | 93 +++ .../third_party/ceres/internal/ceres/file.h | 52 ++ .../ceres/generated/schur_eliminator_2_2_2.cc | 53 ++ .../ceres/generated/schur_eliminator_2_2_3.cc | 53 ++ .../ceres/generated/schur_eliminator_2_2_4.cc | 53 ++ .../ceres/generated/schur_eliminator_2_2_d.cc | 53 ++ .../ceres/generated/schur_eliminator_2_3_3.cc | 53 ++ .../ceres/generated/schur_eliminator_2_3_4.cc | 53 ++ .../ceres/generated/schur_eliminator_2_3_9.cc | 53 ++ .../ceres/generated/schur_eliminator_2_3_d.cc | 53 ++ .../ceres/generated/schur_eliminator_2_4_3.cc | 53 ++ .../ceres/generated/schur_eliminator_2_4_4.cc | 53 ++ .../ceres/generated/schur_eliminator_2_4_d.cc | 53 ++ .../ceres/generated/schur_eliminator_4_4_2.cc | 53 ++ .../ceres/generated/schur_eliminator_4_4_3.cc | 53 ++ .../ceres/generated/schur_eliminator_4_4_4.cc | 53 ++ .../ceres/generated/schur_eliminator_4_4_d.cc | 53 ++ .../ceres/generated/schur_eliminator_d_d_d.cc | 53 ++ .../ceres/gradient_checking_cost_function.cc | 308 ++++++++ .../ceres/gradient_checking_cost_function.h | 85 +++ .../third_party/ceres/internal/ceres/graph.h | 138 ++++ .../ceres/internal/ceres/graph_algorithms.h | 270 +++++++ .../ceres/implicit_schur_complement.cc | 237 ++++++ .../ceres/implicit_schur_complement.h | 176 +++++ .../ceres/internal/ceres/integral_types.h | 92 +++ .../iterative_schur_complement_solver.cc | 150 ++++ .../ceres/iterative_schur_complement_solver.h | 94 +++ .../internal/ceres/levenberg_marquardt.cc | 620 ++++++++++++++++ .../internal/ceres/levenberg_marquardt.h | 65 ++ .../ceres/linear_least_squares_problems.cc | 574 ++++++++++++++ .../ceres/linear_least_squares_problems.h | 77 ++ .../ceres/internal/ceres/linear_operator.cc | 40 + .../ceres/internal/ceres/linear_operator.h | 59 ++ .../ceres/internal/ceres/linear_solver.cc | 87 +++ .../ceres/internal/ceres/linear_solver.h | 291 ++++++++ .../internal/ceres/local_parameterization.cc | 140 ++++ .../ceres/internal/ceres/loss_function.cc | 93 +++ .../ceres/internal/ceres/map_util.h | 129 ++++ .../ceres/internal/ceres/matrix_proto.h | 40 + .../ceres/internal/ceres/minimizer.h | 102 +++ .../third_party/ceres/internal/ceres/mutex.h | 312 ++++++++ .../ceres/internal/ceres/normal_prior.cc | 67 ++ .../ceres/internal/ceres/parameter_block.h | 256 +++++++ .../internal/ceres/partitioned_matrix_view.cc | 315 ++++++++ .../internal/ceres/partitioned_matrix_view.h | 121 +++ .../ceres/internal/ceres/problem.cc | 149 ++++ .../ceres/internal/ceres/problem_impl.cc | 359 +++++++++ .../ceres/internal/ceres/problem_impl.h | 127 ++++ .../ceres/internal/ceres/program.cc | 233 ++++++ .../ceres/internal/ceres/program.h | 128 ++++ .../ceres/internal/ceres/program_evaluator.h | 279 +++++++ .../third_party/ceres/internal/ceres/random.h | 47 ++ .../ceres/internal/ceres/residual_block.cc | 212 ++++++ .../ceres/internal/ceres/residual_block.h | 124 ++++ .../internal/ceres/residual_block_utils.cc | 185 +++++ .../internal/ceres/residual_block_utils.h | 89 +++ .../runtime_numeric_diff_cost_function.cc | 218 ++++++ .../runtime_numeric_diff_cost_function.h | 87 +++ .../internal/ceres/schur_complement_solver.cc | 285 +++++++ .../internal/ceres/schur_complement_solver.h | 182 +++++ .../ceres/internal/ceres/schur_eliminator.cc | 141 ++++ .../ceres/internal/ceres/schur_eliminator.h | 339 +++++++++ .../internal/ceres/schur_eliminator_impl.h | 702 ++++++++++++++++++ .../ceres/internal/ceres/schur_ordering.cc | 113 +++ .../ceres/internal/ceres/schur_ordering.h | 74 ++ .../ceres/scratch_evaluate_preparer.cc | 78 ++ .../ceres/scratch_evaluate_preparer.h | 69 ++ .../ceres/internal/ceres/solver.cc | 230 ++++++ .../ceres/internal/ceres/solver_impl.cc | 693 +++++++++++++++++ .../ceres/internal/ceres/solver_impl.h | 111 +++ .../ceres/internal/ceres/sparse_matrix.cc | 40 + .../ceres/internal/ceres/sparse_matrix.h | 108 +++ .../ceres/sparse_normal_cholesky_solver.cc | 129 ++++ .../ceres/sparse_normal_cholesky_solver.h | 77 ++ .../third_party/ceres/internal/ceres/split.cc | 115 +++ .../ceres/internal/ceres/stl_util.h | 75 ++ .../ceres/internal/ceres/stringprintf.cc | 126 ++++ .../ceres/internal/ceres/stringprintf.h | 89 +++ .../ceres/internal/ceres/suitesparse.cc | 193 +++++ .../ceres/internal/ceres/suitesparse.h | 159 ++++ .../internal/ceres/triplet_sparse_matrix.cc | 299 ++++++++ .../internal/ceres/triplet_sparse_matrix.h | 136 ++++ .../third_party/ceres/internal/ceres/types.cc | 98 +++ .../ceres/internal/ceres/visibility.cc | 150 ++++ .../ceres/internal/ceres/visibility.h | 77 ++ .../ceres/visibility_based_preconditioner.cc | 611 +++++++++++++++ .../ceres/visibility_based_preconditioner.h | 273 +++++++ extern/libmv/third_party/ceres/mkfiles.sh | 4 + extern/libmv/third_party/ceres/patches/series | 1 + source/blenderplayer/CMakeLists.txt | 1 + source/creator/CMakeLists.txt | 1 + 170 files changed, 25035 insertions(+), 37 deletions(-) create mode 100644 extern/libmv/third_party/CMakeLists.txt create mode 100644 extern/libmv/third_party/SConscript create mode 100644 extern/libmv/third_party/ceres/CMakeLists.txt create mode 100644 extern/libmv/third_party/ceres/ChangeLog create mode 100644 extern/libmv/third_party/ceres/LICENSE create mode 100644 extern/libmv/third_party/ceres/README create mode 100644 extern/libmv/third_party/ceres/SConscript create mode 100755 extern/libmv/third_party/ceres/bundle.sh create mode 100644 extern/libmv/third_party/ceres/files.txt create mode 100644 extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/ceres.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/eigen.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/macros.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/port.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/iteration_callback.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/jet.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/local_parameterization.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/loss_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/normal_prior.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/problem.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/rotation.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/solver.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/types.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_structure.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_structure.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/casts.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/cgnr_linear_operator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/collections_port.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/corrector.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/corrector.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/detect_structure.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/evaluator.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/evaluator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/file.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/file.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/graph.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/integral_types.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_operator.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_operator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/loss_function.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/map_util.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/minimizer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/mutex.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/parameter_block.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/problem.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/problem_impl.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/program.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/program.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/random.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/residual_block.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/residual_block.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/solver_impl.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/split.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/stl_util.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/stringprintf.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/suitesparse.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/types.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/visibility.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/visibility.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h create mode 100755 extern/libmv/third_party/ceres/mkfiles.sh create mode 100644 extern/libmv/third_party/ceres/patches/series diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 6be813883ec..cf0ad1102e0 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -32,6 +32,7 @@ set(INC third_party/ssba third_party/ldl/Include ../colamd/Include + third_party/ceres/include ) set(INC_SYS @@ -250,3 +251,5 @@ add_definitions( ) blender_add_lib(extern_libmv "${SRC}" "${INC}" "${INC_SYS}") + +add_subdirectory(third_party) diff --git a/extern/libmv/ChangeLog b/extern/libmv/ChangeLog index 7248e4c9cd9..02b79c93ec2 100644 --- a/extern/libmv/ChangeLog +++ b/extern/libmv/ChangeLog @@ -1,3 +1,54 @@ +commit b813dbe3f46bbbc7e73ac791d4665622e4fc7ba5 +Author: Sergey Sharybin +Date: Wed May 9 19:01:10 2012 +0600 + + Modal solver: Detect rigid transformation between initial frame and current + instead of detecting it between two neighbour frames. + + This prevents accumulation of error and seems to be working better in footages i've tested. + +commit 9254621c76daaf239ec1f535e197ca792eea97b6 +Author: Sergey Sharybin +Date: Wed May 9 18:57:00 2012 +0600 + + Backport changes made by Keir in Blender: + + - Enhance logging in libmv's trackers. + - Cleanups in brute_region_tracker.cc. + +commit d9c56b9d3c63f886d83129ca0ebed1e76d9c93d7 +Author: Sergey Sharybin +Date: Fri Apr 27 16:20:41 2012 +0600 + + Fixes for MinGW64 support by Caleb Joseph with slight modifications by Antony Riakiotakis + + - Functions snprintf and sincos shouldn't be redefined for MinGW64 + - Type pid_t shouldn't be re-defined for MinGW64 + +commit e1902b6938676011607ac99986b8b140bdbf090e +Author: Sergey Sharybin +Date: Fri Apr 27 16:04:19 2012 +0600 + + Fixes for Qt calibration tool + + - Passing directory with images via command line argument now isn't + required -- it there's no such directory specified standard open + dialog might be used for this (before application used to abort + due to accessing to non-existing list element). + - Conversion of source images to grayscale now happens correct. + It was needed to build grayscale palette for 8bit indexed buffer. + +commit 05f1a0a78ad8ff6646d1e8da97e6f7575b891536 +Author: Sergey Sharybin +Date: Sat Apr 14 17:21:29 2012 +0600 + + Make QtTracker compilable again porting it to recent API change and code cleanup: + + - It was using SAD tracker with own API, now it's using standard RegionTracker API + which should make it easier to switch between different trackers. + - Restored LaplaceFilter from old SAD module which convolves images with the + discrete laplacian operator. + commit a44312a7beb2963b8e3bf8015c516d2eff40cc3d Author: Sergey Sharybin Date: Thu Apr 12 13:56:02 2012 +0600 @@ -503,33 +554,3 @@ Author: Matthias Fauconneau Date: Fri Aug 19 18:37:48 2011 +0200 Fix CMake build. - -commit 2ac7281ff6b9545b425dd84fb03bf9c5c98b4de2 -Author: Matthias Fauconneau -Date: Fri Aug 19 17:34:45 2011 +0200 - - Avoid symbol shadowing. - -commit 2a7c3de4acc60e0433b4952f69e30528dbafe0d2 -Author: Matthias Fauconneau -Date: Fri Aug 19 17:22:47 2011 +0200 - - Better dragging behavior when hitting borders. - -commit a14eb3953c9521b2e08ff9ddd45b33ff1f8aeafb -Author: Matthias Fauconneau -Date: Fri Aug 19 17:12:12 2011 +0200 - - Update marker preview to new affine tracking. - -commit 5299ea67043459eda147950e589c2d327a8fbced -Author: Matthias Fauconneau -Date: Fri Aug 19 16:05:54 2011 +0200 - - sqrt takes double precision. - -commit 9f9221ce151d788c49b48f6f293ab2e2f8813978 -Author: Matthias Fauconneau -Date: Fri Aug 19 16:04:37 2011 +0200 - - MSVC compatibility: heap allocate pattern, explicit float cast. diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript index fbb6ee36f85..b47086f3e91 100644 --- a/extern/libmv/SConscript +++ b/extern/libmv/SConscript @@ -30,7 +30,7 @@ src += env.Glob('third_party/ldl/Source/*.c') src += env.Glob('third_party/ssba/Geometry/*.cpp') src += env.Glob('third_party/ssba/Math/*.cpp') -incs = '. ../Eigen3' +incs = '. ../Eigen3 third_party/ceres/include' incs += ' ' + env['BF_PNG_INC'] incs += ' ' + env['BF_ZLIB_INC'] @@ -65,3 +65,5 @@ else: incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include' env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_libmv, cc_compileflags=ccflags_libmv, cxx_compileflags=cxxflags_libmv ) + +SConscript(['third_party/SConscript']) diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh index 30d08cd680a..9baad88a7e2 100755 --- a/extern/libmv/bundle.sh +++ b/extern/libmv/bundle.sh @@ -23,7 +23,7 @@ for p in `cat ./patches/series`; do done rm -rf libmv -rm -rf third_party +rm -rf `find third_party/ -mindepth 1 -maxdepth 1 | grep -v ceres | grep -v CMake | grep -c SCons` cat "files.txt" | while read f; do mkdir -p `dirname $f` @@ -37,14 +37,14 @@ chmod 664 ./third_party/glog/src/windows/*.cc ./third_party/glog/src/windows/*.h sources=`find ./libmv -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | sort -d` headers=`find ./libmv -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d` -third_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep -v glog | sed -r 's/^\.\//\t/' | sort -d` -third_headers=`find ./third_party -type f -iname '*.h' | grep -v glog | sed -r 's/^\.\//\t/' | sort -d` +third_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep -v glog | grep -v ceres | sed -r 's/^\.\//\t/' | sort -d` +third_headers=`find ./third_party -type f -iname '*.h' | grep -v glog | grep -v ceres | sed -r 's/^\.\//\t/' | sort -d` third_glog_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort -d` third_glog_headers=`find ./third_party -type f -iname '*.h' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort -d` src_dir=`find ./libmv -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq` -src_third_dir=`find ./third_party -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq` +src_third_dir=`find ./third_party -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | grep -v ceres | sed -r 's/^\.\//\t/' | sort -d | uniq` src="" win_src="" for x in $src_dir $src_third_dir; do @@ -124,6 +124,7 @@ set(INC third_party/ssba third_party/ldl/Include ../colamd/Include + third_party/ceres/include ) set(INC_SYS @@ -218,6 +219,8 @@ add_definitions( ) blender_add_lib(extern_libmv "\${SRC}" "\${INC}" "\${INC_SYS}") + +add_subdirectory(third_party) EOF cat > SConscript << EOF @@ -244,7 +247,7 @@ defs.append('GOOGLE_GLOG_DLL_DECL=') src = env.Glob("*.cpp") $src -incs = '. ../Eigen3' +incs = '. ../Eigen3 third_party/ceres/include' incs += ' ' + env['BF_PNG_INC'] incs += ' ' + env['BF_ZLIB_INC'] @@ -279,4 +282,6 @@ else: incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include' env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_libmv, cc_compileflags=ccflags_libmv, cxx_compileflags=cxxflags_libmv ) + +SConscript(['third_party/SConscript']) EOF diff --git a/extern/libmv/libmv/image/convolve.cc b/extern/libmv/libmv/image/convolve.cc index be73a1a3263..63ff7d6d8ff 100644 --- a/extern/libmv/libmv/image/convolve.cc +++ b/extern/libmv/libmv/image/convolve.cc @@ -302,4 +302,18 @@ void BoxFilter(const Array3Df &in, BoxFilterVertical(tmp, box_width, out); } +void LaplaceFilter(unsigned char* src, unsigned char* dst, int width, int height, int strength) { + for(int y=1; y 255) d=255; + dst[y*width+x] = d; + } +} + } // namespace libmv diff --git a/extern/libmv/libmv/image/convolve.h b/extern/libmv/libmv/image/convolve.h index c6c995fd674..a005dc31f10 100644 --- a/extern/libmv/libmv/image/convolve.h +++ b/extern/libmv/libmv/image/convolve.h @@ -87,6 +87,16 @@ void BoxFilter(const FloatImage &in, int box_width, FloatImage *out); +/*! + Convolve \a src into \a dst with the discrete laplacian operator. + + \a src and \a dst should be \a width x \a height images. + \a strength is an interpolation coefficient (0-256) between original image and the laplacian. + + \note Make sure the search region is filtered with the same strength as the pattern. +*/ +void LaplaceFilter(unsigned char* src, unsigned char* dst, int width, int height, int strength); + } // namespace libmv #endif // LIBMV_IMAGE_CONVOLVE_H_ diff --git a/extern/libmv/mkfiles.sh b/extern/libmv/mkfiles.sh index fe84c357de4..c7c8c33f725 100755 --- a/extern/libmv/mkfiles.sh +++ b/extern/libmv/mkfiles.sh @@ -1,4 +1,4 @@ #!/bin/sh find ./libmv/ -type f | sed -r 's/^\.\///' | sort > files.txt -find ./third_party/ -type f | sed -r 's/^\.\///' | sort >> files.txt +find ./third_party/ -mindepth 2 -type f | grep -v third_party/ceres | sed -r 's/^\.\///' | sort >> files.txt diff --git a/extern/libmv/third_party/CMakeLists.txt b/extern/libmv/third_party/CMakeLists.txt new file mode 100644 index 00000000000..6212fe480b1 --- /dev/null +++ b/extern/libmv/third_party/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_subdirectory(ceres) diff --git a/extern/libmv/third_party/SConscript b/extern/libmv/third_party/SConscript new file mode 100644 index 00000000000..b05692e385f --- /dev/null +++ b/extern/libmv/third_party/SConscript @@ -0,0 +1,3 @@ +#!/usr/bin/python + +SConscript(['ceres/SConscript']) diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt new file mode 100644 index 00000000000..19158dcfebb --- /dev/null +++ b/extern/libmv/third_party/ceres/CMakeLists.txt @@ -0,0 +1,218 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# Contributor(s): Blender Foundation, +# Sergey Sharybin +# +# ***** END GPL LICENSE BLOCK ***** + +# NOTE: This file is automatically generated by bundle.sh script +# If you're doing changes in this file, please update template +# in that script too + +set(INC + . + ../../../Eigen3 + include + internal + ../gflags +) + +set(INC_SYS +) + +set(SRC + internal/ceres/block_evaluate_preparer.cc + internal/ceres/block_jacobian_writer.cc + internal/ceres/block_jacobi_preconditioner.cc + internal/ceres/block_random_access_dense_matrix.cc + internal/ceres/block_random_access_matrix.cc + internal/ceres/block_random_access_sparse_matrix.cc + internal/ceres/block_sparse_matrix.cc + internal/ceres/block_structure.cc + internal/ceres/canonical_views_clustering.cc + internal/ceres/cgnr_solver.cc + internal/ceres/compressed_row_jacobian_writer.cc + internal/ceres/compressed_row_sparse_matrix.cc + internal/ceres/conditioned_cost_function.cc + internal/ceres/conjugate_gradients_solver.cc + internal/ceres/corrector.cc + internal/ceres/dense_qr_solver.cc + internal/ceres/dense_sparse_matrix.cc + internal/ceres/detect_structure.cc + internal/ceres/evaluator.cc + internal/ceres/file.cc + internal/ceres/generated/schur_eliminator_2_2_2.cc + internal/ceres/generated/schur_eliminator_2_2_3.cc + internal/ceres/generated/schur_eliminator_2_2_4.cc + internal/ceres/generated/schur_eliminator_2_2_d.cc + internal/ceres/generated/schur_eliminator_2_3_3.cc + internal/ceres/generated/schur_eliminator_2_3_4.cc + internal/ceres/generated/schur_eliminator_2_3_9.cc + internal/ceres/generated/schur_eliminator_2_3_d.cc + internal/ceres/generated/schur_eliminator_2_4_3.cc + internal/ceres/generated/schur_eliminator_2_4_4.cc + internal/ceres/generated/schur_eliminator_2_4_d.cc + internal/ceres/generated/schur_eliminator_4_4_2.cc + internal/ceres/generated/schur_eliminator_4_4_3.cc + internal/ceres/generated/schur_eliminator_4_4_4.cc + internal/ceres/generated/schur_eliminator_4_4_d.cc + internal/ceres/generated/schur_eliminator_d_d_d.cc + internal/ceres/gradient_checking_cost_function.cc + internal/ceres/implicit_schur_complement.cc + internal/ceres/iterative_schur_complement_solver.cc + internal/ceres/levenberg_marquardt.cc + internal/ceres/linear_least_squares_problems.cc + internal/ceres/linear_operator.cc + internal/ceres/linear_solver.cc + internal/ceres/local_parameterization.cc + internal/ceres/loss_function.cc + internal/ceres/normal_prior.cc + internal/ceres/partitioned_matrix_view.cc + internal/ceres/problem.cc + internal/ceres/problem_impl.cc + internal/ceres/program.cc + internal/ceres/residual_block.cc + internal/ceres/residual_block_utils.cc + internal/ceres/runtime_numeric_diff_cost_function.cc + internal/ceres/schur_complement_solver.cc + internal/ceres/schur_eliminator.cc + internal/ceres/schur_ordering.cc + internal/ceres/scratch_evaluate_preparer.cc + internal/ceres/solver.cc + internal/ceres/solver_impl.cc + internal/ceres/sparse_matrix.cc + internal/ceres/sparse_normal_cholesky_solver.cc + internal/ceres/split.cc + internal/ceres/stringprintf.cc + internal/ceres/suitesparse.cc + internal/ceres/triplet_sparse_matrix.cc + internal/ceres/types.cc + internal/ceres/visibility_based_preconditioner.cc + internal/ceres/visibility.cc + + include/ceres/autodiff_cost_function.h + include/ceres/ceres.h + include/ceres/conditioned_cost_function.h + include/ceres/cost_function.h + include/ceres/internal/autodiff.h + include/ceres/internal/eigen.h + include/ceres/internal/fixed_array.h + include/ceres/internal/macros.h + include/ceres/internal/manual_constructor.h + include/ceres/internal/port.h + include/ceres/internal/scoped_ptr.h + include/ceres/iteration_callback.h + include/ceres/jet.h + include/ceres/local_parameterization.h + include/ceres/loss_function.h + include/ceres/normal_prior.h + include/ceres/numeric_diff_cost_function.h + include/ceres/problem.h + include/ceres/rotation.h + include/ceres/sized_cost_function.h + include/ceres/solver.h + include/ceres/types.h + internal/ceres/block_evaluate_preparer.h + internal/ceres/block_jacobian_writer.h + internal/ceres/block_jacobi_preconditioner.h + internal/ceres/block_random_access_dense_matrix.h + internal/ceres/block_random_access_matrix.h + internal/ceres/block_random_access_sparse_matrix.h + internal/ceres/block_sparse_matrix.h + internal/ceres/block_structure.h + internal/ceres/canonical_views_clustering.h + internal/ceres/casts.h + internal/ceres/cgnr_linear_operator.h + internal/ceres/cgnr_solver.h + internal/ceres/collections_port.h + internal/ceres/compressed_row_jacobian_writer.h + internal/ceres/compressed_row_sparse_matrix.h + internal/ceres/conjugate_gradients_solver.h + internal/ceres/corrector.h + internal/ceres/dense_jacobian_writer.h + internal/ceres/dense_qr_solver.h + internal/ceres/dense_sparse_matrix.h + internal/ceres/detect_structure.h + internal/ceres/evaluator.h + internal/ceres/file.h + internal/ceres/gradient_checking_cost_function.h + internal/ceres/graph_algorithms.h + internal/ceres/graph.h + internal/ceres/implicit_schur_complement.h + internal/ceres/integral_types.h + internal/ceres/iterative_schur_complement_solver.h + internal/ceres/levenberg_marquardt.h + internal/ceres/linear_least_squares_problems.h + internal/ceres/linear_operator.h + internal/ceres/linear_solver.h + internal/ceres/map_util.h + internal/ceres/matrix_proto.h + internal/ceres/minimizer.h + internal/ceres/mutex.h + internal/ceres/parameter_block.h + internal/ceres/partitioned_matrix_view.h + internal/ceres/problem_impl.h + internal/ceres/program_evaluator.h + internal/ceres/program.h + internal/ceres/random.h + internal/ceres/residual_block.h + internal/ceres/residual_block_utils.h + internal/ceres/runtime_numeric_diff_cost_function.h + internal/ceres/schur_complement_solver.h + internal/ceres/schur_eliminator.h + internal/ceres/schur_eliminator_impl.h + internal/ceres/schur_ordering.h + internal/ceres/scratch_evaluate_preparer.h + internal/ceres/solver_impl.h + internal/ceres/sparse_matrix.h + internal/ceres/sparse_normal_cholesky_solver.h + internal/ceres/stl_util.h + internal/ceres/stringprintf.h + internal/ceres/suitesparse.h + internal/ceres/triplet_sparse_matrix.h + internal/ceres/visibility_based_preconditioner.h + internal/ceres/visibility.h +) + +if(WIN32) + list(APPEND INC + ../glog/src/windows + ) + + if(NOT MINGW) + list(APPEND INC + third_party/msinttypes + ) + endif() +else() + list(APPEND INC + ../glog/src + ) +endif() + +add_definitions( + -DCERES_HAVE_PTHREAD + -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" + -D"CERES_HASH_NAMESPACE_END=}}" + -DCERES_NO_SUITESPARSE + -DCERES_DONT_HAVE_PROTOCOL_BUFFERS +) + +blender_add_lib(extern_ceres "${SRC}" "${INC}" "${INC_SYS}") diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog new file mode 100644 index 00000000000..c652a73c0c1 --- /dev/null +++ b/extern/libmv/third_party/ceres/ChangeLog @@ -0,0 +1,227 @@ +commit d297f8d3d3f5025c24752f0f4c1ec2469a769f99 +Merge: 7e74d81 f8bd7fa +Author: Keir Mierle +Date: Tue May 8 05:39:56 2012 -0700 + + Merge branch 'master' into windows + +commit f8bd7fa9aa9dbf64b6165606630287cf8cf21194 +Author: Keir Mierle +Date: Tue May 8 05:39:32 2012 -0700 + + Small tweaks to the block jacobi preconditioner. + +commit 7e74d81ad57a159f14110eb5348b3bc7990b8bd4 +Merge: ecd7c8d e2a6cdc +Author: Keir Mierle +Date: Mon May 7 07:02:49 2012 -0700 + + Merge branch 'master' into windows + +commit e2a6cdc0816af9d0c77933f5017f137da3d52a35 +Author: Keir Mierle +Date: Mon May 7 06:39:56 2012 -0700 + + Address some of the comments on CGNR patch + + - Rename BlockDiagonalPreconditioner to BlockJacobiPreconditioner + - Include the diagonal in the block jacobi preconditioner. + - Better flag help for eta. + - Enable test for CGNR + - Rename CONJUGATE_GRADIENTS to CGNR. + - etc. + +commit 1b95dc580aa5d89be021c0915e26df83f18013bb +Merge: 211812a 7646039 +Author: Keir Mierle +Date: Mon May 7 04:34:10 2012 -0700 + + Merge branch 'master' of https://code.google.com/p/ceres-solver + +commit 211812a57360d2011cbcfd115cd55e0eb73600db +Author: Keir Mierle +Date: Mon May 7 04:33:50 2012 -0700 + + Better error handling in bundle_adjuster.cc + +commit 7646039ad9672b267495f5b31925473ad3022ac8 +Author: Sameer Agarwal +Date: Sun May 6 22:02:19 2012 -0700 + + Kashif's corrections to the docs + +commit 0d2d34148d10c5c7e924b3ca82ad2b237573ef64 +Author: Sameer Agarwal +Date: Sun May 6 21:16:03 2012 -0700 + + glog minimum version requirements + + Building Ceres requires version 0.3.1 or better of glog. + Fedora 16 ships with a busted version 0.3. + + issue 15 contains the gory details. + + Added a note to the build documentation to this effect. + +commit 39efc5ec4b64b8f5a2c5a3dbacdbc45421221547 +Author: Keir Mierle +Date: Sun May 6 16:09:52 2012 -0700 + + Fix tests broken by the CGNR change. + +commit 3faa08b7f7c4ac73661c6a15a6824c12080dfcb1 +Author: Sameer Agarwal +Date: Sun May 6 16:08:22 2012 -0700 + + Formatting fixed based on Keir's comments and extended the tests + +commit 4f21c68409bc478c431a9b6aedf9e5cfdf11d2f3 +Author: Sameer Agarwal +Date: Sun May 6 15:33:47 2012 -0700 + + Fix the struct weak ordering used by independent set ordering, tests for it + +commit 887b156b917ccd4c172484452b059d33ea45f4f0 +Author: Sameer Agarwal +Date: Sun May 6 15:14:47 2012 -0700 + + fix he degree ordering routine + +commit ecd7c8df2af19404dc394b36bbe96e9db3bce840 +Author: Keir Mierle +Date: Sun May 6 00:09:41 2012 -0700 + + First step towards windows compatibilty + + This adds some small changes to Ceres to make it mostly + compile on Windows. There are still issues with the + hash map use in schur_ordering.cc but I will fix those + shortly. + +commit f7898fba1b92f0e996571b5bfa22a37f5e3644de +Author: Keir Mierle +Date: Sat May 5 20:55:08 2012 -0700 + + Add a general sparse iterative solver: CGNR + + This adds a new LinearOperator which implements symmetric + products of a matrix, and a new CGNR solver to leverage + CG to directly solve the normal equations. This also + includes a block diagonal preconditioner. In experiments + on problem-16, the non-preconditioned version is about + 1/5 the speed of SPARSE_SCHUR, and the preconditioned + version using block cholesky is about 20% slower than + SPARSE_SCHUR. + +commit 0a359d6198d257776a8831c3eb98f64ee91cf836 +Author: Keir Mierle +Date: Sat May 5 20:33:46 2012 -0700 + + Comment formatting. + +commit db4ec9312bb2f1ca7b2337812f6bad6cdd75b227 +Author: Keir Mierle +Date: Sat May 5 20:33:16 2012 -0700 + + Comment formatting + +commit f10163aaf3e57f52551bcd60bbdae873890a49dd +Author: Keir Mierle +Date: Fri May 4 21:33:53 2012 -0700 + + Warn about disabled schur specializations. + + This commit brought to you from 30,000ft. + +commit ad7b2b4aaf3ccc51f2b854febd53a9df54686cfe +Author: Keir Mierle +Date: Fri May 4 20:15:28 2012 -0700 + + Add vim swapfiles to .gitignore + +commit 6447219826bf6e47b0c99d9ff0eaf5e2ba573d79 +Author: Sameer Agarwal +Date: Thu May 3 21:53:07 2012 -0700 + + 1. Changes the tutorial to refer to BriefReport. + 2. Some of the enums have commas at the end. + 3. Fix a bug in the default value of circle_fit.cc in the examples. + +commit 30c5f93c7f88dec49f76168663372772e06f17f5 +Author: Sameer Agarwal +Date: Thu May 3 10:44:43 2012 -0700 + + Rework the glog and gtest path checking to be consistent with the rest of the file and disable the dashboard support enabled by the earlier ctesting related patch. + +commit f10b033eb4aca77919987bc551d16d8a88b10110 +Merge: cc38774 e0a52a9 +Author: Sameer Agarwal +Date: Thu May 3 08:45:20 2012 -0700 + + Merge branch 'ctest' + +commit e0a52a993394e73bc7f7db8d520728926feab83e +Author: Sameer Agarwal +Date: Thu May 3 08:43:34 2012 -0700 + + Arnaus Gelas' patch to add better path searching for gflags and glog + +commit a9b8e815e1c026599734510399b10f4cf014c9cd +Author: Sameer Agarwal +Date: Thu May 3 08:41:52 2012 -0700 + + Arnaus Gelas' patch to add .gitignore + +commit a0cefc3347c32b2065053bbaff4f34d11529d931 +Author: Sameer Agarwal +Date: Thu May 3 08:38:33 2012 -0700 + + Arnaus Gelas' patch to move to Ctest + +commit cc38774d74e287704915282425fbd16818a72ec3 +Author: Keir Mierle +Date: Thu May 3 01:27:50 2012 -0700 + + Clarify ProgramEvaluator comments. + +commit 017c9530df557863f78212fb5ccd02814baa9fa8 +Author: Sameer Agarwal +Date: Wed May 2 08:21:59 2012 -0700 + + Mac OS X build instructions are much simpler, as homebrew takes care of gflags when glog is brought in. Also CMAKE does not need any flags to do the default thing + +commit 92d5ab5f8ae6fe355c30b606a5f230415ee0494b +Author: Keir Mierle +Date: Tue May 1 18:33:08 2012 -0700 + + Link BLAS explicitly on non-Mac platforms + + Fixes issue #3. + +commit df3e54eb4a6b001b7f0560a2da73a5bd7f18615e +Author: Keir Mierle +Date: Tue May 1 18:22:51 2012 -0700 + + Fix link order of CHOLMOD + + This was working by accident due to dynamic linking. Fixes issue #2. + +commit f477a3835329e2b48eb20c34c631a480b0f0d5bf +Author: Keir Mierle +Date: Tue May 1 18:10:48 2012 -0700 + + Fix Eigen search paths + + Fixes issue #1 on http://code.google.com/p/ceres-solver. + +commit 17fbc8ebb894c1d22bb3b0b02ea1394b580120f8 +Author: Sameer Agarwal +Date: Tue May 1 00:21:19 2012 -0700 + + Minor changes to the documentation. Formatting, and typos. + +commit 8ebb0730388045570f22b89fe8672c860cd2ad1b +Author: Keir Mierle +Date: Mon Apr 30 23:09:08 2012 -0700 + + Initial commit of Ceres Solver. diff --git a/extern/libmv/third_party/ceres/LICENSE b/extern/libmv/third_party/ceres/LICENSE new file mode 100644 index 00000000000..2e3ead5ed45 --- /dev/null +++ b/extern/libmv/third_party/ceres/LICENSE @@ -0,0 +1,27 @@ +Ceres Solver - A fast non-linear least squares minimizer +Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +http://code.google.com/p/ceres-solver/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/extern/libmv/third_party/ceres/README b/extern/libmv/third_party/ceres/README new file mode 100644 index 00000000000..8dd8ccf91a1 --- /dev/null +++ b/extern/libmv/third_party/ceres/README @@ -0,0 +1,3 @@ +Ceres Solver - A non-linear least squares minimizer +================================================== +Please see ceres.pdf in docs/ for a tutorial and reference. diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript new file mode 100644 index 00000000000..d8b2b8520d7 --- /dev/null +++ b/extern/libmv/third_party/ceres/SConscript @@ -0,0 +1,34 @@ +#!/usr/bin/python + +# NOTE: This file is automatically generated by bundle.sh script +# If you're doing changes in this file, please update template +# in that script too + +import sys +import os + +Import('env') + +src = [] +defs = [] + +src += env.Glob('internal/ceres/*.cc') +src += env.Glob('internal/ceres/generated/*.cc') + +defs.append('CERES_HAVE_PTHREAD') +defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {') +defs.append('CERES_HASH_NAMESPACE_END=}}') +defs.append('CERES_NO_SUITESPARSE') +defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS') + +incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags' + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + incs += ' ../msinttypes' + + incs += ' ../glog/src/windows' +else: + incs += ' ../glog/src' + +env.BlenderLib ( libname = 'extern_ceres', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137]) diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh new file mode 100755 index 00000000000..d7602f7c171 --- /dev/null +++ b/extern/libmv/third_party/ceres/bundle.sh @@ -0,0 +1,183 @@ +#!/bin/sh + +if [ -d ./.svn ]; then + echo "This script is supposed to work only when using git-svn" + exit 1 +fi + +repo="https://code.google.com/p/ceres-solver/" +branch="windows" +tmp=`mktemp -d` + +GIT="git --git-dir $tmp/ceres/.git --work-tree $tmp/ceres" + +git clone $repo $tmp/ceres + +if [ $branch != "master" ]; then + $GIT checkout -t remotes/origin/$branch +fi + +$GIT log -n 50 > ChangeLog + +for p in `cat ./patches/series`; do + echo "Applying patch $p..." + cat ./patches/$p | patch -d $tmp/ceres -p1 +done + +rm -rf include +rm -rf internal + +cat "files.txt" | while read f; do + mkdir -p `dirname $f` + cp $tmp/ceres/$f $f +done + +rm -rf $tmp + +sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | sort -d` +headers=`find ./include ./internal -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d` + +src_dir=`find ./internal -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq` +src="" +for x in $src_dir $src_third_dir; do + t="" + + if test `echo "$x" | grep -c glog ` -eq 1; then + continue; + fi + + if stat $x/*.cpp > /dev/null 2>&1; then + t="src += env.Glob('`echo $x'/*.cpp'`')" + fi + + if stat $x/*.c > /dev/null 2>&1; then + if [ -z "$t" ]; then + t="src += env.Glob('`echo $x'/*.c'`')" + else + t="$t + env.Glob('`echo $x'/*.c'`')" + fi + fi + + if stat $x/*.cc > /dev/null 2>&1; then + if [ -z "$t" ]; then + t="src += env.Glob('`echo $x'/*.cc'`')" + else + t="$t + env.Glob('`echo $x'/*.cc'`')" + fi + fi + + if [ -z "$src" ]; then + src=$t + else + src=`echo "$src\n$t"` + fi +done + +cat > CMakeLists.txt << EOF +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# Contributor(s): Blender Foundation, +# Sergey Sharybin +# +# ***** END GPL LICENSE BLOCK ***** + +# NOTE: This file is automatically generated by bundle.sh script +# If you're doing changes in this file, please update template +# in that script too + +set(INC + . + ../../../Eigen3 + include + internal + ../gflags +) + +set(INC_SYS +) + +set(SRC +${sources} + +${headers} +) + +if(WIN32) + list(APPEND INC + ../glog/src/windows + ) + + if(NOT MINGW) + list(APPEND INC + third_party/msinttypes + ) + endif() +else() + list(APPEND INC + ../glog/src + ) +endif() + +add_definitions( + -DCERES_HAVE_PTHREAD + -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" + -D"CERES_HASH_NAMESPACE_END=}}" + -DCERES_NO_SUITESPARSE + -DCERES_DONT_HAVE_PROTOCOL_BUFFERS +) + +blender_add_lib(extern_ceres "\${SRC}" "\${INC}" "\${INC_SYS}") +EOF + +cat > SConscript << EOF +#!/usr/bin/python + +# NOTE: This file is automatically generated by bundle.sh script +# If you're doing changes in this file, please update template +# in that script too + +import sys +import os + +Import('env') + +src = [] +defs = [] + +$src + +defs.append('CERES_HAVE_PTHREAD') +defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {') +defs.append('CERES_HASH_NAMESPACE_END=}}') +defs.append('CERES_NO_SUITESPARSE') +defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS') + +incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags' + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + incs += ' ../msinttypes' + + incs += ' ../glog/src/windows' +else: + incs += ' ../glog/src' + +env.BlenderLib ( libname = 'extern_ceres', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137]) +EOF diff --git a/extern/libmv/third_party/ceres/files.txt b/extern/libmv/third_party/ceres/files.txt new file mode 100644 index 00000000000..e9d7f585260 --- /dev/null +++ b/extern/libmv/third_party/ceres/files.txt @@ -0,0 +1,150 @@ +include/ceres/autodiff_cost_function.h +include/ceres/ceres.h +include/ceres/conditioned_cost_function.h +include/ceres/cost_function.h +include/ceres/internal/autodiff.h +include/ceres/internal/eigen.h +include/ceres/internal/fixed_array.h +include/ceres/internal/macros.h +include/ceres/internal/manual_constructor.h +include/ceres/internal/port.h +include/ceres/internal/scoped_ptr.h +include/ceres/iteration_callback.h +include/ceres/jet.h +include/ceres/local_parameterization.h +include/ceres/loss_function.h +include/ceres/normal_prior.h +include/ceres/numeric_diff_cost_function.h +include/ceres/problem.h +include/ceres/rotation.h +include/ceres/sized_cost_function.h +include/ceres/solver.h +include/ceres/types.h +internal/ceres/block_evaluate_preparer.cc +internal/ceres/block_evaluate_preparer.h +internal/ceres/block_jacobian_writer.cc +internal/ceres/block_jacobian_writer.h +internal/ceres/block_jacobi_preconditioner.cc +internal/ceres/block_jacobi_preconditioner.h +internal/ceres/block_random_access_dense_matrix.cc +internal/ceres/block_random_access_dense_matrix.h +internal/ceres/block_random_access_matrix.cc +internal/ceres/block_random_access_matrix.h +internal/ceres/block_random_access_sparse_matrix.cc +internal/ceres/block_random_access_sparse_matrix.h +internal/ceres/block_sparse_matrix.cc +internal/ceres/block_sparse_matrix.h +internal/ceres/block_structure.cc +internal/ceres/block_structure.h +internal/ceres/canonical_views_clustering.cc +internal/ceres/canonical_views_clustering.h +internal/ceres/casts.h +internal/ceres/cgnr_linear_operator.h +internal/ceres/cgnr_solver.cc +internal/ceres/cgnr_solver.h +internal/ceres/collections_port.h +internal/ceres/compressed_row_jacobian_writer.cc +internal/ceres/compressed_row_jacobian_writer.h +internal/ceres/compressed_row_sparse_matrix.cc +internal/ceres/compressed_row_sparse_matrix.h +internal/ceres/conditioned_cost_function.cc +internal/ceres/conjugate_gradients_solver.cc +internal/ceres/conjugate_gradients_solver.h +internal/ceres/corrector.cc +internal/ceres/corrector.h +internal/ceres/dense_jacobian_writer.h +internal/ceres/dense_qr_solver.cc +internal/ceres/dense_qr_solver.h +internal/ceres/dense_sparse_matrix.cc +internal/ceres/dense_sparse_matrix.h +internal/ceres/detect_structure.cc +internal/ceres/detect_structure.h +internal/ceres/evaluator.cc +internal/ceres/evaluator.h +internal/ceres/file.cc +internal/ceres/file.h +internal/ceres/generated/schur_eliminator_2_2_2.cc +internal/ceres/generated/schur_eliminator_2_2_3.cc +internal/ceres/generated/schur_eliminator_2_2_4.cc +internal/ceres/generated/schur_eliminator_2_2_d.cc +internal/ceres/generated/schur_eliminator_2_3_3.cc +internal/ceres/generated/schur_eliminator_2_3_4.cc +internal/ceres/generated/schur_eliminator_2_3_9.cc +internal/ceres/generated/schur_eliminator_2_3_d.cc +internal/ceres/generated/schur_eliminator_2_4_3.cc +internal/ceres/generated/schur_eliminator_2_4_4.cc +internal/ceres/generated/schur_eliminator_2_4_d.cc +internal/ceres/generated/schur_eliminator_4_4_2.cc +internal/ceres/generated/schur_eliminator_4_4_3.cc +internal/ceres/generated/schur_eliminator_4_4_4.cc +internal/ceres/generated/schur_eliminator_4_4_d.cc +internal/ceres/generated/schur_eliminator_d_d_d.cc +internal/ceres/gradient_checking_cost_function.cc +internal/ceres/gradient_checking_cost_function.h +internal/ceres/graph_algorithms.h +internal/ceres/graph.h +internal/ceres/implicit_schur_complement.cc +internal/ceres/implicit_schur_complement.h +internal/ceres/integral_types.h +internal/ceres/iterative_schur_complement_solver.cc +internal/ceres/iterative_schur_complement_solver.h +internal/ceres/levenberg_marquardt.cc +internal/ceres/levenberg_marquardt.h +internal/ceres/linear_least_squares_problems.cc +internal/ceres/linear_least_squares_problems.h +internal/ceres/linear_operator.cc +internal/ceres/linear_operator.h +internal/ceres/linear_solver.cc +internal/ceres/linear_solver.h +internal/ceres/local_parameterization.cc +internal/ceres/loss_function.cc +internal/ceres/map_util.h +internal/ceres/matrix_proto.h +internal/ceres/minimizer.h +internal/ceres/mutex.h +internal/ceres/normal_prior.cc +internal/ceres/parameter_block.h +internal/ceres/partitioned_matrix_view.cc +internal/ceres/partitioned_matrix_view.h +internal/ceres/problem.cc +internal/ceres/problem_impl.cc +internal/ceres/problem_impl.h +internal/ceres/program.cc +internal/ceres/program_evaluator.h +internal/ceres/program.h +internal/ceres/random.h +internal/ceres/residual_block.cc +internal/ceres/residual_block.h +internal/ceres/residual_block_utils.cc +internal/ceres/residual_block_utils.h +internal/ceres/runtime_numeric_diff_cost_function.cc +internal/ceres/runtime_numeric_diff_cost_function.h +internal/ceres/schur_complement_solver.cc +internal/ceres/schur_complement_solver.h +internal/ceres/schur_eliminator.cc +internal/ceres/schur_eliminator.h +internal/ceres/schur_eliminator_impl.h +internal/ceres/schur_ordering.cc +internal/ceres/schur_ordering.h +internal/ceres/scratch_evaluate_preparer.cc +internal/ceres/scratch_evaluate_preparer.h +internal/ceres/solver.cc +internal/ceres/solver_impl.cc +internal/ceres/solver_impl.h +internal/ceres/sparse_matrix.cc +internal/ceres/sparse_matrix.h +internal/ceres/sparse_normal_cholesky_solver.cc +internal/ceres/sparse_normal_cholesky_solver.h +internal/ceres/split.cc +internal/ceres/stl_util.h +internal/ceres/stringprintf.cc +internal/ceres/stringprintf.h +internal/ceres/suitesparse.cc +internal/ceres/suitesparse.h +internal/ceres/triplet_sparse_matrix.cc +internal/ceres/triplet_sparse_matrix.h +internal/ceres/types.cc +internal/ceres/visibility_based_preconditioner.cc +internal/ceres/visibility_based_preconditioner.h +internal/ceres/visibility.cc +internal/ceres/visibility.h diff --git a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h new file mode 100644 index 00000000000..0ac6240dfab --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h @@ -0,0 +1,170 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Helpers for making CostFunctions as needed by the least squares framework, +// with Jacobians computed via automatic differentiation. For more information +// on automatic differentation, see the wikipedia article at +// http://en.wikipedia.org/wiki/Automatic_differentiation +// +// To get an auto differentiated cost function, you must define a class with a +// templated operator() (a functor) that computes the cost function in terms of +// the template parameter T. The autodiff framework substitutes appropriate +// "jet" objects for T in order to compute the derivative when necessary, but +// this is hidden, and you should write the function as if T were a scalar type +// (e.g. a double-precision floating point number). +// +// The function must write the computed value in the last argument (the only +// non-const one) and return true to indicate success. +// +// For example, consider a scalar error e = k - x'y, where both x and y are +// two-dimensional column vector parameters, the prime sign indicates +// transposition, and k is a constant. The form of this error, which is the +// difference between a constant and an expression, is a common pattern in least +// squares problems. For example, the value x'y might be the model expectation +// for a series of measurements, where there is an instance of the cost function +// for each measurement k. +// +// The actual cost added to the total problem is e^2, or (k - x'k)^2; however, +// the squaring is implicitly done by the optimization framework. +// +// To write an auto-differentiable cost function for the above model, first +// define the object +// +// class MyScalarCostFunction { +// MyScalarCostFunction(double k): k_(k) {} +// +// template +// bool operator()(const T* const x , const T* const y, T* e) const { +// e[0] = T(k_) - x[0] * y[0] + x[1] * y[1]; +// return true; +// } +// +// private: +// double k_; +// }; +// +// Note that in the declaration of operator() the input parameters x and y come +// first, and are passed as const pointers to arrays of T. If there were three +// input parameters, then the third input parameter would come after y. The +// output is always the last parameter, and is also a pointer to an array. In +// the example above, e is a scalar, so only e[0] is set. +// +// Then given this class definition, the auto differentiated cost function for +// it can be constructed as follows. +// +// CostFunction* cost_function +// = new AutoDiffCostFunction( +// new MyScalarCostFunction(1.0)); ^ ^ ^ +// | | | +// Dimension of residual ------+ | | +// Dimension of x ----------------+ | +// Dimension of y -------------------+ +// +// In this example, there is usually an instance for each measumerent of k. +// +// In the instantiation above, the template parameters following +// "MyScalarCostFunction", "1, 2, 2", describe the functor as computing a +// 1-dimensional output from two arguments, both 2-dimensional. +// +// The framework can currently accommodate cost functions of up to 6 independent +// variables, and there is no limit on the dimensionality of each of them. +// +// WARNING #1: Since the functor will get instantiated with different types for +// T, you must to convert from other numeric types to T before mixing +// computations with other variables of type T. In the example above, this is +// seen where instead of using k_ directly, k_ is wrapped with T(k_). +// +// WARNING #2: A common beginner's error when first using autodiff cost +// functions is to get the sizing wrong. In particular, there is a tendency to +// set the template parameters to (dimension of residual, number of parameters) +// instead of passing a dimension parameter for *every parameter*. In the +// example above, that would be , which is missing +// the last '2' argument. Please be careful when setting the size parameters. + +#ifndef CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_ +#define CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_ + +#include +#include "ceres/internal/autodiff.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/sized_cost_function.h" + +namespace ceres { + +// A cost function which computes the derivative of the cost with respect to the +// parameters (a.k.a. the jacobian) using an autodifferentiation framework. The +// first template argument is the functor object, described in the header +// comment. The second argument is the dimension of the residual, and subsequent +// arguments describe the size of the Nth parameter, one per parameter. +// +// The constructor, which takes a cost functor, takes ownership of the functor. +template // Number of parameters in block 5. +class AutoDiffCostFunction : + public SizedCostFunction { + public: + // Takes ownership of functor. + explicit AutoDiffCostFunction(CostFunctor* functor) : functor_(functor) {} + + virtual ~AutoDiffCostFunction() {} + + // Implementation details follow; clients of the autodiff cost function should + // not have to examine below here. + // + // To handle varardic cost functions, some template magic is needed. It's + // mostly hidden inside autodiff.h. + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + if (!jacobians) { + return internal::VariadicEvaluate< + CostFunctor, double, M, N0, N1, N2, N3, N4, N5> + ::Call(*functor_, parameters, residuals); + } + return internal::AutoDiff::Differentiate(*functor_, + parameters, + residuals, + jacobians); + } + + private: + internal::scoped_ptr functor_; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/ceres.h b/extern/libmv/third_party/ceres/include/ceres/ceres.h new file mode 100644 index 00000000000..22aaf8ff21a --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/ceres.h @@ -0,0 +1,48 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// This is a forwarding header containing the public symbols exported from +// Ceres. Anything in the "ceres" namespace is available for use. + +#ifndef CERES_PUBLIC_CERES_H_ +#define CERES_PUBLIC_CERES_H_ + +#include "ceres/autodiff_cost_function.h" +#include "ceres/cost_function.h" +#include "ceres/iteration_callback.h" +#include "ceres/local_parameterization.h" +#include "ceres/loss_function.h" +#include "ceres/numeric_diff_cost_function.h" +#include "ceres/problem.h" +#include "ceres/sized_cost_function.h" +#include "ceres/solver.h" +#include "ceres/types.h" + +#endif // CERES_PUBLIC_CERES_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h new file mode 100644 index 00000000000..498d36ee55a --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h @@ -0,0 +1,97 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: wjr@google.com (William Rucklidge) +// +// This file contains a cost function that can apply a transformation to +// each residual value before they are square-summed. + +#ifndef CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_ +#define CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_ + +#include + +#include "ceres/cost_function.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +// This class allows you to apply different conditioning to the residual +// values of a wrapped cost function. An example where this is useful is +// where you have an existing cost function that produces N values, but you +// want the total cost to be something other than just the sum of these +// squared values - maybe you want to apply a different scaling to some +// values, to change their contribution to the cost. +// +// Usage: +// +// // my_cost_function produces N residuals +// CostFunction* my_cost_function = ... +// CHECK_EQ(N, my_cost_function->num_residuals()); +// vector conditioners; +// +// // Make N 1x1 cost functions (1 parameter, 1 residual) +// CostFunction* f_1 = ... +// conditioners.push_back(f_1); +// ... +// CostFunction* f_N = ... +// conditioners.push_back(f_N); +// ConditionedCostFunction* ccf = +// new ConditionedCostFunction(my_cost_function, conditioners); +// +// Now ccf's residual i (i=0..N-1) will be passed though the i'th conditioner. +// +// ccf_residual[i] = f_i(my_cost_function_residual[i]) +// +// and the Jacobian will be affected appropriately. +class ConditionedCostFunction : public CostFunction { + public: + // Builds a cost function based on a wrapped cost function, and a + // per-residual conditioner. Takes ownership of all of the wrapped cost + // functions, or not, depending on the ownership parameter. Conditioners + // may be NULL, in which case the corresponding residual is not modified. + ConditionedCostFunction(CostFunction* wrapped_cost_function, + const vector& conditioners, + Ownership ownership); + virtual ~ConditionedCostFunction(); + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const; + + private: + internal::scoped_ptr wrapped_cost_function_; + vector conditioners_; + Ownership ownership_; +}; + +} // namespace ceres + + +#endif // CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/cost_function.h b/extern/libmv/third_party/ceres/include/ceres/cost_function.h new file mode 100644 index 00000000000..84403d90636 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/cost_function.h @@ -0,0 +1,127 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.m (Keir Mierle) +// +// This is the interface through which the least squares solver accesses the +// residual and Jacobian of the least squares problem. Users are expected to +// subclass CostFunction to define their own terms in the least squares problem. +// +// It is recommended that users define templated residual functors for use as +// arguments for AutoDiffCostFunction (see autodiff_cost_function.h), instead of +// directly implementing the CostFunction interface. This often results in both +// shorter code and faster execution than hand-coded derivatives. However, +// specialized cases may demand direct implementation of the lower-level +// CostFunction interface; for example, this is true when calling legacy code +// which is not templated on numeric types. + +#ifndef CERES_PUBLIC_COST_FUNCTION_H_ +#define CERES_PUBLIC_COST_FUNCTION_H_ + +#include +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/types.h" + +namespace ceres { + +// This class implements the computation of the cost (a.k.a. residual) terms as +// a function of the input (control) variables, and is the interface for users +// to describe their least squares problem to Ceres. In other words, this is the +// modelling layer between users and the Ceres optimizer. The signature of the +// function (number and sizes of input parameter blocks and number of outputs) +// is stored in parameter_block_sizes_ and num_residuals_ respectively. User +// code inheriting from this class is expected to set these two members with the +// corresponding accessors. This information will be verified by the Problem +// when added with AddResidualBlock(). +class CostFunction { + public: + CostFunction() : num_residuals_(0) {} + + virtual ~CostFunction() {} + + // Inputs: + // + // parameters is an array of pointers to arrays containing the + // various parameter blocks. parameters has the same number of + // elements as parameter_block_sizes_. Parameter blocks are in the + // same order as parameter_block_sizes_.i.e., + // + // parameters_[i] = double[parameter_block_sizes_[i]] + // + // Outputs: + // + // residuals is an array of size num_residuals_. + // + // jacobians is an array of size parameter_block_sizes_ containing + // pointers to storage for jacobian blocks corresponding to each + // parameter block. Jacobian blocks are in the same order as + // parameter_block_sizes, i.e. jacobians[i], is an + // array that contains num_residuals_* parameter_block_sizes_[i] + // elements. Each jacobian block is stored in row-major order, i.e., + // + // jacobians[i][r*parameter_block_size_[i] + c] = + // d residual[r] / d parameters[i][c] + // + // If jacobians is NULL, then no derivatives are returned; this is + // the case when computing cost only. If jacobians[i] is NULL, then + // the jacobian block corresponding to the i'th parameter block must + // not to be returned. + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const = 0; + + const vector& parameter_block_sizes() const { + return parameter_block_sizes_; + } + + int num_residuals() const { + return num_residuals_; + } + + protected: + vector* mutable_parameter_block_sizes() { + return ¶meter_block_sizes_; + } + + void set_num_residuals(int num_residuals) { + num_residuals_ = num_residuals; + } + + private: + // Cost function signature metadata: number of inputs & their sizes, + // number of outputs (residuals). + vector parameter_block_sizes_; + int num_residuals_; + DISALLOW_COPY_AND_ASSIGN(CostFunction); +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h new file mode 100644 index 00000000000..1a9d396c9ef --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h @@ -0,0 +1,374 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Computation of the Jacobian matrix for vector-valued functions of multiple +// variables, using automatic differentiation based on the implementation of +// dual numbers in jet.h. Before reading the rest of this file, it is adivsable +// to read jet.h's header comment in detail. +// +// The helper wrapper AutoDiff::Differentiate() computes the jacobian of +// functors with templated operator() taking this form: +// +// struct F { +// template +// bool operator(const T *x, const T *y, ..., T *z) { +// // Compute z[] based on x[], y[], ... +// // return true if computation succeeded, false otherwise. +// } +// }; +// +// All inputs and outputs may be vector-valued. +// +// To understand how jets are used to compute the jacobian, a +// picture may help. Consider a vector-valued function, F, returning 3 +// dimensions and taking a vector-valued parameter of 4 dimensions: +// +// y x +// [ * ] F [ * ] +// [ * ] <--- [ * ] +// [ * ] [ * ] +// [ * ] +// +// Similar to the 2-parameter example for f described in jet.h, computing the +// jacobian dy/dx is done by substutiting a suitable jet object for x and all +// intermediate steps of the computation of F. Since x is has 4 dimensions, use +// a Jet. +// +// Before substituting a jet object for x, the dual components are set +// appropriately for each dimension of x: +// +// y x +// [ * | * * * * ] f [ * | 1 0 0 0 ] x0 +// [ * | * * * * ] <--- [ * | 0 1 0 0 ] x1 +// [ * | * * * * ] [ * | 0 0 1 0 ] x2 +// ---+--- [ * | 0 0 0 1 ] x3 +// | ^ ^ ^ ^ +// dy/dx | | | +----- infinitesimal for x3 +// | | +------- infinitesimal for x2 +// | +--------- infinitesimal for x1 +// +----------- infinitesimal for x0 +// +// The reason to set the internal 4x4 submatrix to the identity is that we wish +// to take the derivative of y separately with respect to each dimension of x. +// Each column of the 4x4 identity is therefore for a single component of the +// independent variable x. +// +// Then the jacobian of the mapping, dy/dx, is the 3x4 sub-matrix of the +// extended y vector, indicated in the above diagram. +// +// Functors with multiple parameters +// --------------------------------- +// In practice, it is often convenient to use a function f of two or more +// vector-valued parameters, for example, x[3] and z[6]. Unfortunately, the jet +// framework is designed for a single-parameter vector-valued input. The wrapper +// in this file addresses this issue adding support for functions with one or +// more parameter vectors. +// +// To support multiple parameters, all the parameter vectors are concatenated +// into one and treated as a single parameter vector, except that since the +// functor expects different inputs, we need to construct the jets as if they +// were part of a single parameter vector. The extended jets are passed +// separately for each parameter. +// +// For example, consider a functor F taking two vector parameters, p[2] and +// q[3], and producing an output y[4]: +// +// struct F { +// template +// bool operator(const T *p, const T *q, T *z) { +// // ... +// } +// }; +// +// In this case, the necessary jet type is Jet. Here is a +// visualization of the jet objects in this case: +// +// Dual components for p ----+ +// | +// -+- +// y [ * | 1 0 | 0 0 0 ] --- p[0] +// [ * | 0 1 | 0 0 0 ] --- p[1] +// [ * | . . | + + + ] | +// [ * | . . | + + + ] v +// [ * | . . | + + + ] <--- F(p, q) +// [ * | . . | + + + ] ^ +// ^^^ ^^^^^ | +// dy/dp dy/dq [ * | 0 0 | 1 0 0 ] --- q[0] +// [ * | 0 0 | 0 1 0 ] --- q[1] +// [ * | 0 0 | 0 0 1 ] --- q[2] +// --+-- +// | +// Dual components for q --------------+ +// +// where the 4x2 submatrix (marked with ".") and 4x3 submatrix (marked with "+" +// of y in the above diagram are the derivatives of y with respect to p and q +// respectively. This is how autodiff works for functors taking multiple vector +// valued arguments (up to 6). +// +// Jacobian NULL pointers +// ---------------------- +// In general, the functions below will accept NULL pointers for all or some of +// the Jacobian parameters, meaning that those Jacobians will not be computed. + +#ifndef CERES_PUBLIC_INTERNAL_AUTODIFF_H_ +#define CERES_PUBLIC_INTERNAL_AUTODIFF_H_ + +#include + +#include +#include "ceres/jet.h" +#include "ceres/internal/fixed_array.h" + +namespace ceres { +namespace internal { + +// Extends src by a 1st order pertubation for every dimension and puts it in +// dst. The size of src is N. Since this is also used for perturbations in +// blocked arrays, offset is used to shift which part of the jet the +// perturbation occurs. This is used to set up the extended x augmented by an +// identity matrix. The JetT type should be a Jet type, and T should be a +// numeric type (e.g. double). For example, +// +// 0 1 2 3 4 5 6 7 8 +// dst[0] [ * | . . | 1 0 0 | . . . ] +// dst[1] [ * | . . | 0 1 0 | . . . ] +// dst[2] [ * | . . | 0 0 1 | . . . ] +// +// is what would get put in dst if N was 3, offset was 3, and the jet type JetT +// was 8-dimensional. +template +inline void Make1stOrderPerturbation(int offset, int N, const T *src, + JetT *dst) { + DCHECK(src); + DCHECK(dst); + for (int j = 0; j < N; ++j) { + dst[j] = JetT(src[j], offset + j); + } +} + +// Takes the 0th order part of src, assumed to be a Jet type, and puts it in +// dst. This is used to pick out the "vector" part of the extended y. +template +inline void Take0thOrderPart(int M, const JetT *src, T dst) { + DCHECK(src); + for (int i = 0; i < M; ++i) { + dst[i] = src[i].a; + } +} + +// Takes N 1st order parts, starting at index N0, and puts them in the M x N +// matrix 'dst'. This is used to pick out the "matrix" parts of the extended y. +template +inline void Take1stOrderPart(const JetT *src, T *dst) { + DCHECK(src); + DCHECK(dst); + // TODO(keir): Change Jet to use a single array, where v[0] is the + // non-infinitesimal part rather than "a". That way it's possible to use a + // single memcpy or eigen operation, rather than the explicit loop. The loop + // doesn't exploit any SSE or other intrinsics. + for (int i = 0; i < M; ++i) { + for (int j = 0; j < N; ++j) { + dst[N * i + j] = src[i].v[N0 + j]; + } + } +} + +// This block of quasi-repeated code calls the user-supplied functor, which may +// take a variable number of arguments. This is accomplished by specializing the +// struct based on the size of the trailing parameters; parameters with 0 size +// are assumed missing. +// +// Supporting variadic functions is the primary source of complexity in the +// autodiff implementation. + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + input[2], + input[3], + input[4], + input[5], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + input[2], + input[3], + input[4], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + input[2], + input[3], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + input[2], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + output); + } +}; + +// This is in a struct because default template parameters on a function are not +// supported in C++03 (though it is available in C++0x). N0 through N5 are the +// dimension of the input arguments to the user supplied functor. +template +struct AutoDiff { + static bool Differentiate(const Functor& functor, + T const *const *parameters, + T *function_value, + T **jacobians) { + typedef Jet JetT; + + DCHECK_GT(N0, 0) + << "Cost functions must have at least one parameter block."; + DCHECK((!N1 && !N2 && !N3 && !N4 && !N5) || + ((N1 > 0) && !N2 && !N3 && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0))) + << "Zero block cannot precede a non-zero block. Block sizes are " + << "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", " + << N3 << ", " << N4 << ", " << N5; + + DCHECK_GT(kNumOutputs, 0); + + FixedArray x( + N0 + N1 + N2 + N3 + N4 + N5 + kNumOutputs); + + // It's ugly, but it works. + const int jet0 = 0; + const int jet1 = N0; + const int jet2 = N0 + N1; + const int jet3 = N0 + N1 + N2; + const int jet4 = N0 + N1 + N2 + N3; + const int jet5 = N0 + N1 + N2 + N3 + N4; + const int jet6 = N0 + N1 + N2 + N3 + N4 + N5; + + const JetT *unpacked_parameters[6] = { + x.get() + jet0, + x.get() + jet1, + x.get() + jet2, + x.get() + jet3, + x.get() + jet4, + x.get() + jet5, + }; + JetT *output = x.get() + jet6; + +#define CERES_MAKE_1ST_ORDER_PERTURBATION(i) \ + if (N ## i) { \ + internal::Make1stOrderPerturbation(jet ## i, \ + N ## i, \ + parameters[i], \ + x.get() + jet ## i); \ + } + CERES_MAKE_1ST_ORDER_PERTURBATION(0); + CERES_MAKE_1ST_ORDER_PERTURBATION(1); + CERES_MAKE_1ST_ORDER_PERTURBATION(2); + CERES_MAKE_1ST_ORDER_PERTURBATION(3); + CERES_MAKE_1ST_ORDER_PERTURBATION(4); + CERES_MAKE_1ST_ORDER_PERTURBATION(5); +#undef CERES_MAKE_1ST_ORDER_PERTURBATION + + if (!VariadicEvaluate::Call( + functor, unpacked_parameters, output)) { + return false; + } + + internal::Take0thOrderPart(kNumOutputs, output, function_value); + +#define CERES_TAKE_1ST_ORDER_PERTURBATION(i) \ + if (N ## i) { \ + if (jacobians[i]) { \ + internal::Take1stOrderPart(output, \ + jacobians[i]); \ + } \ + } + CERES_TAKE_1ST_ORDER_PERTURBATION(0); + CERES_TAKE_1ST_ORDER_PERTURBATION(1); + CERES_TAKE_1ST_ORDER_PERTURBATION(2); + CERES_TAKE_1ST_ORDER_PERTURBATION(3); + CERES_TAKE_1ST_ORDER_PERTURBATION(4); + CERES_TAKE_1ST_ORDER_PERTURBATION(5); +#undef CERES_TAKE_1ST_ORDER_PERTURBATION + return true; + } +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_AUTODIFF_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h b/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h new file mode 100644 index 00000000000..be76f9eff98 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h @@ -0,0 +1,80 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_EIGEN_H_ +#define CERES_INTERNAL_EIGEN_H_ + +#include "Eigen/Core" + +namespace ceres { + +using Eigen::Dynamic; +using Eigen::RowMajor; + +typedef Eigen::Matrix Vector; +typedef Eigen::Matrix Matrix; +typedef Eigen::Map VectorRef; +typedef Eigen::Map MatrixRef; +typedef Eigen::Map AlignedMatrixRef; +typedef Eigen::Map ConstVectorRef; +typedef Eigen::Map ConstAlignedMatrixRef; +typedef Eigen::Map ConstMatrixRef; + +// C++ does not support templated typdefs, thus the need for this +// struct so that we can support statically sized Matrix and Maps. +template +struct EigenTypes { + typedef Eigen::Matrix + Matrix; + + typedef Eigen::Map< + Eigen::Matrix > + MatrixRef; + + typedef Eigen::Matrix + Vector; + + typedef Eigen::Map < + Eigen::Matrix > + VectorRef; + + + typedef Eigen::Map< + const Eigen::Matrix > + ConstMatrixRef; + + typedef Eigen::Map < + const Eigen::Matrix > + ConstVectorRef; +}; + +} // namespace ceres + +#endif // CERES_INTERNAL_EIGEN_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h new file mode 100644 index 00000000000..30cc5fc4a6c --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h @@ -0,0 +1,193 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: rennie@google.com (Jeffrey Rennie) +// Author: sanjay@google.com (Sanjay Ghemawat) -- renamed to FixedArray + +#ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_ +#define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_ + +#include +#include +#include "ceres/internal/manual_constructor.h" + +namespace ceres { +namespace internal { + +// A FixedArray represents a non-resizable array of T where the +// length of the array does not need to be a compile time constant. +// +// FixedArray allocates small arrays inline, and large arrays on +// the heap. It is a good replacement for non-standard and deprecated +// uses of alloca() and variable length arrays (a GCC extension). +// +// FixedArray keeps performance fast for small arrays, because it +// avoids heap operations. It also helps reduce the chances of +// accidentally overflowing your stack if large input is passed to +// your function. +// +// Also, FixedArray is useful for writing portable code. Not all +// compilers support arrays of dynamic size. + +// Most users should not specify an inline_elements argument and let +// FixedArray<> automatically determine the number of elements +// to store inline based on sizeof(T). +// +// If inline_elements is specified, the FixedArray<> implementation +// will store arrays of length <= inline_elements inline. +// +// Finally note that unlike vector FixedArray will not zero-initialize +// simple types like int, double, bool, etc. +// +// Non-POD types will be default-initialized just like regular vectors or +// arrays. + +#if defined(_WIN64) + typedef __int64 ssize_t; +#elif defined(_WIN32) + typedef __int32 ssize_t; +#endif + +template +class FixedArray { + public: + // For playing nicely with stl: + typedef T value_type; + typedef T* iterator; + typedef T const* const_iterator; + typedef T& reference; + typedef T const& const_reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + typedef size_t size_type; + + // REQUIRES: n >= 0 + // Creates an array object that can store "n" elements. + // + // FixedArray will not zero-initialiaze POD (simple) types like int, + // double, bool, etc. + // Non-POD types will be default-initialized just like regular vectors or + // arrays. + explicit FixedArray(size_type n); + + // Releases any resources. + ~FixedArray(); + + // Returns the length of the array. + inline size_type size() const { return size_; } + + // Returns the memory size of the array in bytes. + inline size_t memsize() const { return size_ * sizeof(T); } + + // Returns a pointer to the underlying element array. + inline const T* get() const { return &array_[0].element; } + inline T* get() { return &array_[0].element; } + + // REQUIRES: 0 <= i < size() + // Returns a reference to the "i"th element. + inline T& operator[](size_type i) { + DCHECK_GE(i, 0); + DCHECK_LT(i, size_); + return array_[i].element; + } + + // REQUIRES: 0 <= i < size() + // Returns a reference to the "i"th element. + inline const T& operator[](size_type i) const { + DCHECK_GE(i, 0); + DCHECK_LT(i, size_); + return array_[i].element; + } + + inline iterator begin() { return &array_[0].element; } + inline iterator end() { return &array_[size_].element; } + + inline const_iterator begin() const { return &array_[0].element; } + inline const_iterator end() const { return &array_[size_].element; } + + private: + // Container to hold elements of type T. This is necessary to handle + // the case where T is a a (C-style) array. The size of InnerContainer + // and T must be the same, otherwise callers' assumptions about use + // of this code will be broken. + struct InnerContainer { + T element; + }; + + // How many elements should we store inline? + // a. If not specified, use a default of 256 bytes (256 bytes + // seems small enough to not cause stack overflow or unnecessary + // stack pollution, while still allowing stack allocation for + // reasonably long character arrays. + // b. Never use 0 length arrays (not ISO C++) + static const size_type S1 = ((inline_elements < 0) + ? (256/sizeof(T)) : inline_elements); + static const size_type S2 = (S1 <= 0) ? 1 : S1; + static const size_type kInlineElements = S2; + + size_type const size_; + InnerContainer* const array_; + + // Allocate some space, not an array of elements of type T, so that we can + // skip calling the T constructors and destructors for space we never use. + ManualConstructor inline_space_[kInlineElements]; +}; + +// Implementation details follow + +template +inline FixedArray::FixedArray(typename FixedArray::size_type n) + : size_(n), + array_((n <= kInlineElements + ? reinterpret_cast(inline_space_) + : new InnerContainer[n])) { + DCHECK_GE(n, 0); + + // Construct only the elements actually used. + if (array_ == reinterpret_cast(inline_space_)) { + for (int i = 0; i != size_; ++i) { + inline_space_[i].Init(); + } + } +} + +template +inline FixedArray::~FixedArray() { + if (array_ != reinterpret_cast(inline_space_)) { + delete[] array_; + } else { + for (int i = 0; i != size_; ++i) { + inline_space_[i].Destroy(); + } + } +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h new file mode 100644 index 00000000000..0cfd773bcca --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h @@ -0,0 +1,154 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// +// Various Google-specific macros. +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// any changes here, make sure that you're not breaking any platforms. + +#ifndef CERES_PUBLIC_INTERNAL_MACROS_H_ +#define CERES_PUBLIC_INTERNAL_MACROS_H_ + +#include // For size_t. + +// A macro to disallow the copy constructor and operator= functions +// This should be used in the private: declarations for a class +// +// For disallowing only assign or copy, write the code directly, but declare +// the intend in a comment, for example: +// void operator=(const TypeName&); // DISALLOW_ASSIGN +// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken +// semantically, one should either use disallow both or neither. Try to +// avoid these in new code. +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +// A macro to disallow all the implicit constructors, namely the +// default constructor, copy constructor and operator= functions. +// +// This should be used in the private: declarations for a class +// that wants to prevent anyone from instantiating it. This is +// especially useful for classes containing only static methods. +#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + DISALLOW_COPY_AND_ASSIGN(TypeName) + +// The arraysize(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. If you use arraysize on +// a pointer by mistake, you will get a compile-time error. +// +// One caveat is that arraysize() doesn't accept any array of an +// anonymous type or a type defined inside a function. In these rare +// cases, you have to use the unsafe ARRAYSIZE() macro below. This is +// due to a limitation in C++'s template system. The limitation might +// eventually be removed, but it hasn't happened yet. + +// This template function declaration is used in defining arraysize. +// Note that the function doesn't need an implementation, as we only +// use its type. +template +char (&ArraySizeHelper(T (&array)[N]))[N]; + +// That gcc wants both of these prototypes seems mysterious. VC, for +// its part, can't decide which to use (another mystery). Matching of +// template overloads: the final frontier. +#ifndef _WIN32 +template +char (&ArraySizeHelper(const T (&array)[N]))[N]; +#endif + +#define arraysize(array) (sizeof(ArraySizeHelper(array))) + +// ARRAYSIZE performs essentially the same calculation as arraysize, +// but can be used on anonymous types or types defined inside +// functions. It's less safe than arraysize as it accepts some +// (although not all) pointers. Therefore, you should use arraysize +// whenever possible. +// +// The expression ARRAYSIZE(a) is a compile-time constant of type +// size_t. +// +// ARRAYSIZE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using ARRAYSIZE, you are (wrongfully) giving it a pointer. +// You should only use ARRAYSIZE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +// +// Kudos to Jorg Brown for this simple and elegant implementation. +// +// - wan 2005-11-16 +// +// Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE. However, +// the definition comes from the over-broad windows.h header that +// introduces a macro, ERROR, that conflicts with the logging framework +// that Ceres uses. Instead, rename ARRAYSIZE to CERES_ARRAYSIZE. +#define CERES_ARRAYSIZE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast(!(sizeof(a) % sizeof(*(a))))) + +// Tell the compiler to warn about unused return values for functions declared +// with this macro. The macro should be used on function declarations +// following the argument list: +// +// Sprocket* AllocateSprocket() MUST_USE_RESULT; +// +#undef MUST_USE_RESULT +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \ + && !defined(COMPILER_ICC) +#define MUST_USE_RESULT __attribute__ ((warn_unused_result)) +#else +#define MUST_USE_RESULT +#endif + +#endif // CERES_PUBLIC_INTERNAL_MACROS_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h new file mode 100644 index 00000000000..a1d1f444e36 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h @@ -0,0 +1,214 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: kenton@google.com (Kenton Varda) +// +// ManualConstructor statically-allocates space in which to store some +// object, but does not initialize it. You can then call the constructor +// and destructor for the object yourself as you see fit. This is useful +// for memory management optimizations, where you want to initialize and +// destroy an object multiple times but only allocate it once. +// +// (When I say ManualConstructor statically allocates space, I mean that +// the ManualConstructor object itself is forced to be the right size.) + +#ifndef CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_ +#define CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_ + +#include + +namespace ceres { +namespace internal { + +// ------- Define ALIGNED_CHAR_ARRAY -------------------------------- + +#ifndef ALIGNED_CHAR_ARRAY + +// Because MSVC and older GCCs require that the argument to their alignment +// construct to be a literal constant integer, we use a template instantiated +// at all the possible powers of two. +template struct AlignType { }; +template struct AlignType<0, size> { typedef char result[size]; }; +#if defined(_MSC_VER) +#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __declspec(align(X)) +#define BASE_PORT_H_ALIGN_OF(T) __alignof(T) +#elif defined(__GNUC__) +#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __attribute__((aligned(X))) +#define BASE_PORT_H_ALIGN_OF(T) __alignof__(T) +#endif + +#if defined(BASE_PORT_H_ALIGN_ATTRIBUTE) + +#define BASE_PORT_H_ALIGNTYPE_TEMPLATE(X) \ + template struct AlignType { \ + typedef BASE_PORT_H_ALIGN_ATTRIBUTE(X) char result[size]; \ + } + +BASE_PORT_H_ALIGNTYPE_TEMPLATE(1); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(2); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(4); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(8); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(16); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(32); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(64); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(128); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(256); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(512); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(1024); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(2048); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(4096); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(8192); +// Any larger and MSVC++ will complain. + +#define ALIGNED_CHAR_ARRAY(T, Size) \ + typename AlignType::result + +#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE +#undef BASE_PORT_H_ALIGN_ATTRIBUTE + +#else // defined(BASE_PORT_H_ALIGN_ATTRIBUTE) +#define ALIGNED_CHAR_ARRAY you_must_define_ALIGNED_CHAR_ARRAY_for_your_compiler +#endif // defined(BASE_PORT_H_ALIGN_ATTRIBUTE) + +#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE +#undef BASE_PORT_H_ALIGN_ATTRIBUTE + +#endif // ALIGNED_CHAR_ARRAY + +template +class ManualConstructor { + public: + // No constructor or destructor because one of the most useful uses of + // this class is as part of a union, and members of a union cannot have + // constructors or destructors. And, anyway, the whole point of this + // class is to bypass these. + + inline Type* get() { + return reinterpret_cast(space_); + } + inline const Type* get() const { + return reinterpret_cast(space_); + } + + inline Type* operator->() { return get(); } + inline const Type* operator->() const { return get(); } + + inline Type& operator*() { return *get(); } + inline const Type& operator*() const { return *get(); } + + // You can pass up to four constructor arguments as arguments of Init(). + inline void Init() { + new(space_) Type; + } + + template + inline void Init(const T1& p1) { + new(space_) Type(p1); + } + + template + inline void Init(const T1& p1, const T2& p2) { + new(space_) Type(p1, p2); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3) { + new(space_) Type(p1, p2, p3); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) { + new(space_) Type(p1, p2, p3, p4); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5) { + new(space_) Type(p1, p2, p3, p4, p5); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6) { + new(space_) Type(p1, p2, p3, p4, p5, p6); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7, const T8& p8) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7, const T8& p8, + const T9& p9) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7, const T8& p8, + const T9& p9, const T10& p10) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7, const T8& p8, + const T9& p9, const T10& p10, const T11& p11) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); + } + + inline void Destroy() { + get()->~Type(); + } + + private: + ALIGNED_CHAR_ARRAY(Type, 1) space_; +}; + +#undef ALIGNED_CHAR_ARRAY + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/port.h b/extern/libmv/third_party/ceres/include/ceres/internal/port.h new file mode 100644 index 00000000000..9a3e5cced58 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/port.h @@ -0,0 +1,44 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_PUBLIC_INTERNAL_PORT_H_ +#define CERES_PUBLIC_INTERNAL_PORT_H_ + +namespace ceres { + +// It is unfortunate that this import of the entire standard namespace is +// necessary. The reasons are historical and won't be explained here, but +// suffice to say it is not a mistake and can't be removed without breaking +// things outside of the Ceres optimization package. +using namespace std; + +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_PORT_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h b/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h new file mode 100644 index 00000000000..44f198b339d --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h @@ -0,0 +1,311 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: jorg@google.com (Jorg Brown) +// +// This is an implementation designed to match the anticipated future TR2 +// implementation of the scoped_ptr class, and its closely-related brethren, +// scoped_array, scoped_ptr_malloc, and make_scoped_ptr. + +#ifndef CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_ +#define CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_ + +#include +#include +#include + +namespace ceres { +namespace internal { + +template class scoped_ptr; +template class scoped_ptr_malloc; +template class scoped_array; + +template +scoped_ptr make_scoped_ptr(C *); + +// A scoped_ptr is like a T*, except that the destructor of scoped_ptr +// automatically deletes the pointer it holds (if any). That is, scoped_ptr +// owns the T object that it points to. Like a T*, a scoped_ptr may hold +// either NULL or a pointer to a T object. Also like T*, scoped_ptr is +// thread-compatible, and once you dereference it, you get the threadsafety +// guarantees of T. +// +// The size of a scoped_ptr is small: sizeof(scoped_ptr) == sizeof(C*) +template +class scoped_ptr { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to intializing with NULL. + // There is no way to create an uninitialized scoped_ptr. + // The input parameter must be allocated with new. + explicit scoped_ptr(C* p = NULL) : ptr_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_ptr() { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != ptr_) { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + ptr_ = p; + } + } + + // Accessors to get the owned object. + // operator* and operator-> will assert() if there is no current object. + C& operator*() const { + assert(ptr_ != NULL); + return *ptr_; + } + C* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + C* get() const { return ptr_; } + + // Comparison operators. + // These return whether a scoped_ptr and a raw pointer refer to + // the same object, not just to two different but equal objects. + bool operator==(const C* p) const { return ptr_ == p; } + bool operator!=(const C* p) const { return ptr_ != p; } + + // Swap two scoped pointers. + void swap(scoped_ptr& p2) { + C* tmp = ptr_; + ptr_ = p2.ptr_; + p2.ptr_ = tmp; + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() { + C* retVal = ptr_; + ptr_ = NULL; + return retVal; + } + + private: + C* ptr_; + + // google3 friend class that can access copy ctor (although if it actually + // calls a copy ctor, there will be a problem) see below + friend scoped_ptr make_scoped_ptr(C *p); + + // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't + // make sense, and if C2 == C, it still doesn't make sense because you should + // never have the same object owned by two different scoped_ptrs. + template bool operator==(scoped_ptr const& p2) const; + template bool operator!=(scoped_ptr const& p2) const; + + // Disallow evil constructors + scoped_ptr(const scoped_ptr&); + void operator=(const scoped_ptr&); +}; + +// Free functions +template +inline void swap(scoped_ptr& p1, scoped_ptr& p2) { + p1.swap(p2); +} + +template +inline bool operator==(const C* p1, const scoped_ptr& p2) { + return p1 == p2.get(); +} + +template +inline bool operator==(const C* p1, const scoped_ptr& p2) { + return p1 == p2.get(); +} + +template +inline bool operator!=(const C* p1, const scoped_ptr& p2) { + return p1 != p2.get(); +} + +template +inline bool operator!=(const C* p1, const scoped_ptr& p2) { + return p1 != p2.get(); +} + +template +scoped_ptr make_scoped_ptr(C *p) { + // This does nothing but to return a scoped_ptr of the type that the passed + // pointer is of. (This eliminates the need to specify the name of T when + // making a scoped_ptr that is used anonymously/temporarily.) From an + // access control point of view, we construct an unnamed scoped_ptr here + // which we return and thus copy-construct. Hence, we need to have access + // to scoped_ptr::scoped_ptr(scoped_ptr const &). However, it is guaranteed + // that we never actually call the copy constructor, which is a good thing + // as we would call the temporary's object destructor (and thus delete p) + // if we actually did copy some object, here. + return scoped_ptr(p); +} + +// scoped_array is like scoped_ptr, except that the caller must allocate +// with new [] and the destructor deletes objects with delete []. +// +// As with scoped_ptr, a scoped_array either points to an object +// or is NULL. A scoped_array owns the object that it points to. +// scoped_array is thread-compatible, and once you index into it, +// the returned objects have only the threadsafety guarantees of T. +// +// Size: sizeof(scoped_array) == sizeof(C*) +template +class scoped_array { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to intializing with NULL. + // There is no way to create an uninitialized scoped_array. + // The input parameter must be allocated with new []. + explicit scoped_array(C* p = NULL) : array_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_array() { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != array_) { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + array_ = p; + } + } + + // Get one element of the current object. + // Will assert() if there is no current object, or index i is negative. + C& operator[](std::ptrdiff_t i) const { + assert(i >= 0); + assert(array_ != NULL); + return array_[i]; + } + + // Get a pointer to the zeroth element of the current object. + // If there is no current object, return NULL. + C* get() const { + return array_; + } + + // Comparison operators. + // These return whether a scoped_array and a raw pointer refer to + // the same array, not just to two different but equal arrays. + bool operator==(const C* p) const { return array_ == p; } + bool operator!=(const C* p) const { return array_ != p; } + + // Swap two scoped arrays. + void swap(scoped_array& p2) { + C* tmp = array_; + array_ = p2.array_; + p2.array_ = tmp; + } + + // Release an array. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() { + C* retVal = array_; + array_ = NULL; + return retVal; + } + + private: + C* array_; + + // Forbid comparison of different scoped_array types. + template bool operator==(scoped_array const& p2) const; + template bool operator!=(scoped_array const& p2) const; + + // Disallow evil constructors + scoped_array(const scoped_array&); + void operator=(const scoped_array&); +}; + +// Free functions +template +inline void swap(scoped_array& p1, scoped_array& p2) { + p1.swap(p2); +} + +template +inline bool operator==(const C* p1, const scoped_array& p2) { + return p1 == p2.get(); +} + +template +inline bool operator==(const C* p1, const scoped_array& p2) { + return p1 == p2.get(); +} + +template +inline bool operator!=(const C* p1, const scoped_array& p2) { + return p1 != p2.get(); +} + +template +inline bool operator!=(const C* p1, const scoped_array& p2) { + return p1 != p2.get(); +} + +// This class wraps the c library function free() in a class that can be +// passed as a template argument to scoped_ptr_malloc below. +class ScopedPtrMallocFree { + public: + inline void operator()(void* x) const { + free(x); + } +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h new file mode 100644 index 00000000000..88da992d0c5 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h @@ -0,0 +1,159 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// When an iteration callback is specified, Ceres calls the callback after each +// optimizer step and pass it an IterationSummary object, defined below. + +#ifndef CERES_PUBLIC_ITERATION_CALLBACK_H_ +#define CERES_PUBLIC_ITERATION_CALLBACK_H_ + +#include "ceres/types.h" + +namespace ceres { + +// This struct describes the state of the optimizer after each +// iteration of the minimization. +struct IterationSummary { + // Current iteration number. + int32 iteration; + + // Whether or not the algorithm made progress in this iteration. + bool step_is_successful; + + // Value of the objective function. + double cost; + + // Change in the value of the objective function in this + // iteration. This can be positive or negative. Negative change + // means that the step was not successful. + double cost_change; + + // Infinity norm of the gradient vector. + double gradient_max_norm; + + // 2-norm of the size of the step computed by the optimization + // algorithm. + double step_norm; + + // For trust region algorithms, the ratio of the actual change in + // cost and the change in the cost of the linearized approximation. + double relative_decrease; + + // Value of the regularization parameter for Levenberg-Marquardt + // algorithm at the end of the current iteration. + double mu; + + // For the inexact step Levenberg-Marquardt algorithm, this is the + // relative accuracy with which the Newton(LM) step is solved. This + // number affects only the iterative solvers capable of solving + // linear systems inexactly. Factorization-based exact solvers + // ignore it. + double eta; + + // Number of iterations taken by the linear solver to solve for the + // Newton step. + int linear_solver_iterations; + + // TODO(sameeragarwal): Change to use a higher precision timer using + // clock_gettime. + // Time (in seconds) spent inside the linear least squares solver. + int iteration_time_sec; + + // Time (in seconds) spent inside the linear least squares solver. + int linear_solver_time_sec; +}; + +// Interface for specifying callbacks that are executed at the end of +// each iteration of the Minimizer. The solver uses the return value +// of operator() to decide whether to continue solving or to +// terminate. The user can return three values. +// +// SOLVER_ABORT indicates that the callback detected an abnormal +// situation. The solver returns without updating the parameter blocks +// (unless Solver::Options::update_state_every_iteration is set +// true). Solver returns with Solver::Summary::termination_type set to +// USER_ABORT. +// +// SOLVER_TERMINATE_SUCCESSFULLY indicates that there is no need to +// optimize anymore (some user specified termination criterion has +// been met). Solver returns with Solver::Summary::termination_type +// set to USER_SUCCESS. +// +// SOLVER_CONTINUE indicates that the solver should continue +// optimizing. +// +// For example, the following Callback is used internally by Ceres to +// log the progress of the optimization. +// +// Callback for logging the state of the minimizer to STDERR or STDOUT +// depending on the user's preferences and logging level. +// +// class LoggingCallback : public IterationCallback { +// public: +// explicit LoggingCallback(bool log_to_stdout) +// : log_to_stdout_(log_to_stdout) {} +// +// ~LoggingCallback() {} +// +// CallbackReturnType operator()(const IterationSummary& summary) { +// const char* kReportRowFormat = +// "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e " +// "rho:% 3.2e mu:% 3.2e eta:% 3.2e li:% 3d"; +// string output = StringPrintf(kReportRowFormat, +// summary.iteration, +// summary.cost, +// summary.cost_change, +// summary.gradient_max_norm, +// summary.step_norm, +// summary.relative_decrease, +// summary.mu, +// summary.eta, +// summary.linear_solver_iterations); +// if (log_to_stdout_) { +// cout << output << endl; +// } else { +// VLOG(1) << output; +// } +// return SOLVER_CONTINUE; +// } +// +// private: +// const bool log_to_stdout_; +// }; +// +class IterationCallback { + public: + virtual ~IterationCallback() {} + virtual CallbackReturnType operator()(const IterationSummary& summary) = 0; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_ITERATION_CALLBACK_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/jet.h b/extern/libmv/third_party/ceres/include/ceres/jet.h new file mode 100644 index 00000000000..f73c6988951 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/jet.h @@ -0,0 +1,671 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A simple implementation of N-dimensional dual numbers, for automatically +// computing exact derivatives of functions. +// +// While a complete treatment of the mechanics of automatic differentation is +// beyond the scope of this header (see +// http://en.wikipedia.org/wiki/Automatic_differentiation for details), the +// basic idea is to extend normal arithmetic with an extra element, "e," often +// denoted with the greek symbol epsilon, such that e != 0 but e^2 = 0. Dual +// numbers are extensions of the real numbers analogous to complex numbers: +// whereas complex numbers augment the reals by introducing an imaginary unit i +// such that i^2 = -1, dual numbers introduce an "infinitesimal" unit e such +// that e^2 = 0. Dual numbers have two components: the "real" component and the +// "infinitesimal" component, generally written as x + y*e. Surprisingly, this +// leads to a convenient method for computing exact derivatives without needing +// to manipulate complicated symbolic expressions. +// +// For example, consider the function +// +// f(x) = x^2 , +// +// evaluated at 10. Using normal arithmetic, f(10) = 100, and df/dx(10) = 20. +// Next, augument 10 with an infinitesimal to get: +// +// f(10 + e) = (10 + e)^2 +// = 100 + 2 * 10 * e + e^2 +// = 100 + 20 * e -+- +// -- | +// | +--- This is zero, since e^2 = 0 +// | +// +----------------- This is df/dx! +// +// Note that the derivative of f with respect to x is simply the infinitesimal +// component of the value of f(x + e). So, in order to take the derivative of +// any function, it is only necessary to replace the numeric "object" used in +// the function with one extended with infinitesimals. The class Jet, defined in +// this header, is one such example of this, where substitution is done with +// templates. +// +// To handle derivatives of functions taking multiple arguments, different +// infinitesimals are used, one for each variable to take the derivative of. For +// example, consider a scalar function of two scalar parameters x and y: +// +// f(x, y) = x^2 + x * y +// +// Following the technique above, to compute the derivatives df/dx and df/dy for +// f(1, 3) involves doing two evaluations of f, the first time replacing x with +// x + e, the second time replacing y with y + e. +// +// For df/dx: +// +// f(1 + e, y) = (1 + e)^2 + (1 + e) * 3 +// = 1 + 2 * e + 3 + 3 * e +// = 4 + 5 * e +// +// --> df/dx = 5 +// +// For df/dy: +// +// f(1, 3 + e) = 1^2 + 1 * (3 + e) +// = 1 + 3 + e +// = 4 + e +// +// --> df/dy = 1 +// +// To take the gradient of f with the implementation of dual numbers ("jets") in +// this file, it is necessary to create a single jet type which has components +// for the derivative in x and y, and passing them to a templated version of f: +// +// template +// T f(const T &x, const T &y) { +// return x * x + x * y; +// } +// +// // The "2" means there should be 2 dual number components. +// Jet x(0); // Pick the 0th dual number for x. +// Jet y(1); // Pick the 1st dual number for y. +// Jet z = f(x, y); +// +// LG << "df/dx = " << z.a[0] +// << "df/dy = " << z.a[1]; +// +// Most users should not use Jet objects directly; a wrapper around Jet objects, +// which makes computing the derivative, gradient, or jacobian of templated +// functors simple, is in autodiff.h. Even autodiff.h should not be used +// directly; instead autodiff_cost_function.h is typically the file of interest. +// +// For the more mathematically inclined, this file implements first-order +// "jets". A 1st order jet is an element of the ring +// +// T[N] = T[t_1, ..., t_N] / (t_1, ..., t_N)^2 +// +// which essentially means that each jet consists of a "scalar" value 'a' from T +// and a 1st order perturbation vector 'v' of length N: +// +// x = a + \sum_i v[i] t_i +// +// A shorthand is to write an element as x = a + u, where u is the pertubation. +// Then, the main point about the arithmetic of jets is that the product of +// perturbations is zero: +// +// (a + u) * (b + v) = ab + av + bu + uv +// = ab + (av + bu) + 0 +// +// which is what operator* implements below. Addition is simpler: +// +// (a + u) + (b + v) = (a + b) + (u + v). +// +// The only remaining question is how to evaluate the function of a jet, for +// which we use the chain rule: +// +// f(a + u) = f(a) + f'(a) u +// +// where f'(a) is the (scalar) derivative of f at a. +// +// By pushing these things through sufficiently and suitably templated +// functions, we can do automatic differentiation. Just be sure to turn on +// function inlining and common-subexpression elimination, or it will be very +// slow! +// +// WARNING: Most Ceres users should not directly include this file or know the +// details of how jets work. Instead the suggested method for automatic +// derivatives is to use autodiff_cost_function.h, which is a wrapper around +// both jets.h and autodiff.h to make taking derivatives of cost functions for +// use in Ceres easier. + +#ifndef CERES_PUBLIC_JET_H_ +#define CERES_PUBLIC_JET_H_ + +#include +#include +#include // NOLINT +#include + +#include "Eigen/Core" + +// Visual Studio 2010 or older version +#if defined(_MSC_VER) && _MSC_VER <= 1600 +namespace std { +inline bool isfinite(double x) { return _finite(x); } +inline bool isinf (double x) { return !_finite(x) && !_isnan(x); } +inline bool isnan (double x) { return _isnan(x); } +inline bool isnormal(double x) { return _finite(x) && x != 0.0; } +} // namespace std +#endif + +namespace ceres { + +template +struct Jet { + enum { DIMENSION = N }; + + // Default-construct "a" because otherwise this can lead to false errors about + // uninitialized uses when other classes relying on default constructed T + // (where T is a Jet). This usually only happens in opt mode. Note that + // the C++ standard mandates that e.g. default constructed doubles are + // initialized to 0.0; see sections 8.5 of the C++03 standard. + Jet() : a() {} + + // Constructor from scalar: a + 0. + explicit Jet(const T& value) { + a = value; + v.setZero(); + } + + // Constructor from scalar plus variable: a + t_i. + Jet(const T& value, int k) { + a = value; + v.setZero(); + v[k] = T(1.0); + } + + // Compound operators + Jet& operator+=(const Jet &y) { + *this = *this + y; + return *this; + } + + Jet& operator-=(const Jet &y) { + *this = *this - y; + return *this; + } + + Jet& operator*=(const Jet &y) { + *this = *this * y; + return *this; + } + + Jet& operator/=(const Jet &y) { + *this = *this / y; + return *this; + } + + T a; // The scalar part. + Eigen::Matrix v; // The infinitesimal part. +}; + +// Unary + +template inline +Jet const& operator+(const Jet& f) { + return f; +} + +// TODO(keir): Try adding __attribute__((always_inline)) to these functions to +// see if it causes a performance increase. + +// Unary - +template inline +Jet operator-(const Jet&f) { + Jet g; + g.a = -f.a; + g.v = -f.v; + return g; +} + +// Binary + +template inline +Jet operator+(const Jet& f, + const Jet& g) { + Jet h; + h.a = f.a + g.a; + h.v = f.v + g.v; + return h; +} + +// Binary + with a scalar: x + s +template inline +Jet operator+(const Jet& f, T s) { + Jet h; + h.a = f.a + s; + h.v = f.v; + return h; +} + +// Binary + with a scalar: s + x +template inline +Jet operator+(T s, const Jet& f) { + Jet h; + h.a = f.a + s; + h.v = f.v; + return h; +} + +// Binary - +template inline +Jet operator-(const Jet& f, + const Jet& g) { + Jet h; + h.a = f.a - g.a; + h.v = f.v - g.v; + return h; +} + +// Binary - with a scalar: x - s +template inline +Jet operator-(const Jet& f, T s) { + Jet h; + h.a = f.a - s; + h.v = f.v; + return h; +} + +// Binary - with a scalar: s - x +template inline +Jet operator-(T s, const Jet& f) { + Jet h; + h.a = s - f.a; + h.v = -f.v; + return h; +} + +// Binary * +template inline +Jet operator*(const Jet& f, + const Jet& g) { + Jet h; + h.a = f.a * g.a; + h.v = f.a * g.v + f.v * g.a; + return h; +} + +// Binary * with a scalar: x * s +template inline +Jet operator*(const Jet& f, T s) { + Jet h; + h.a = f.a * s; + h.v = f.v * s; + return h; +} + +// Binary * with a scalar: s * x +template inline +Jet operator*(T s, const Jet& f) { + Jet h; + h.a = f.a * s; + h.v = f.v * s; + return h; +} + +// Binary / +template inline +Jet operator/(const Jet& f, + const Jet& g) { + Jet h; + // This uses: + // + // a + u (a + u)(b - v) (a + u)(b - v) + // ----- = -------------- = -------------- + // b + v (b + v)(b - v) b^2 + // + // which holds because v*v = 0. + h.a = f.a / g.a; + h.v = (f.v - f.a / g.a * g.v) / g.a; + return h; +} + +// Binary / with a scalar: s / x +template inline +Jet operator/(T s, const Jet& g) { + Jet h; + h.a = s / g.a; + h.v = - s * g.v / (g.a * g.a); + return h; +} + +// Binary / with a scalar: x / s +template inline +Jet operator/(const Jet& f, T s) { + Jet h; + h.a = f.a / s; + h.v = f.v / s; + return h; +} + +// Binary comparison operators for both scalars and jets. +#define CERES_DEFINE_JET_COMPARISON_OPERATOR(op) \ +template inline \ +bool operator op(const Jet& f, const Jet& g) { \ + return f.a op g.a; \ +} \ +template inline \ +bool operator op(const T& s, const Jet& g) { \ + return s op g.a; \ +} \ +template inline \ +bool operator op(const Jet& f, const T& s) { \ + return f.a op s; \ +} +CERES_DEFINE_JET_COMPARISON_OPERATOR( < ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( <= ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( > ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( >= ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( == ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( != ) // NOLINT +#undef CERES_DEFINE_JET_COMPARISON_OPERATOR + +// Pull some functions from namespace std. +// +// This is necessary because we want to use the same name (e.g. 'sqrt') for +// double-valued and Jet-valued functions, but we are not allowed to put +// Jet-valued functions inside namespace std. +// +// Missing: cosh, sinh, tanh, tan +// TODO(keir): Switch to "using". +inline double abs (double x) { return std::abs(x); } +inline double log (double x) { return std::log(x); } +inline double exp (double x) { return std::exp(x); } +inline double sqrt (double x) { return std::sqrt(x); } +inline double cos (double x) { return std::cos(x); } +inline double acos (double x) { return std::acos(x); } +inline double sin (double x) { return std::sin(x); } +inline double asin (double x) { return std::asin(x); } +inline bool isfinite(double x) { return std::isfinite(x); } +inline bool isinf (double x) { return std::isinf(x); } +inline bool isnan (double x) { return std::isnan(x); } +inline bool isnormal(double x) { return std::isnormal(x); } +inline double pow (double x, double y) { return std::pow(x, y); } +inline double atan2(double y, double x) { return std::atan2(y, x); } + +// In general, f(a + h) ~= f(a) + f'(a) h, via the chain rule. + +// abs(x + h) ~= x + h or -(x + h) +template inline +Jet abs(const Jet& f) { + return f.a < T(0.0) ? -f : f; +} + +// log(a + h) ~= log(a) + h / a +template inline +Jet log(const Jet& f) { + Jet g; + g.a = log(f.a); + g.v = f.v / f.a; + return g; +} + +// exp(a + h) ~= exp(a) + exp(a) h +template inline +Jet exp(const Jet& f) { + Jet g; + g.a = exp(f.a); + g.v = g.a * f.v; + return g; +} + +// sqrt(a + h) ~= sqrt(a) + h / (2 sqrt(a)) +template inline +Jet sqrt(const Jet& f) { + Jet g; + g.a = sqrt(f.a); + g.v = f.v / (T(2.0) * g.a); + return g; +} + +// cos(a + h) ~= cos(a) - sin(a) h +template inline +Jet cos(const Jet& f) { + Jet g; + g.a = cos(f.a); + T sin_a = sin(f.a); + g.v = - sin_a * f.v; + return g; +} + +// acos(a + h) ~= acos(a) - 1 / sqrt(1 - a^2) h +template inline +Jet acos(const Jet& f) { + Jet g; + g.a = acos(f.a); + g.v = - T(1.0) / sqrt(T(1.0) - f.a * f.a) * f.v; + return g; +} + +// sin(a + h) ~= sin(a) + cos(a) h +template inline +Jet sin(const Jet& f) { + Jet g; + g.a = sin(f.a); + T cos_a = cos(f.a); + g.v = cos_a * f.v; + return g; +} + +// asin(a + h) ~= asin(a) + 1 / sqrt(1 - a^2) h +template inline +Jet asin(const Jet& f) { + Jet g; + g.a = asin(f.a); + g.v = T(1.0) / sqrt(T(1.0) - f.a * f.a) * f.v; + return g; +} + +// Jet Classification. It is not clear what the appropriate semantics are for +// these classifications. This picks that isfinite and isnormal are "all" +// operations, i.e. all elements of the jet must be finite for the jet itself to +// be finite (or normal). For isnan and isinf, the answer is less clear. This +// takes a "any" approach for isnan and isinf such that if any part of a jet is +// nan or inf, then the entire jet is nan or inf. This leads to strange +// situations like a jet can be both isinf and isnan, but in practice the "any" +// semantics are the most useful for e.g. checking that derivatives are sane. + +// The jet is finite if all parts of the jet are finite. +template inline +bool isfinite(const Jet& f) { + if (!isfinite(f.a)) { + return false; + } + for (int i = 0; i < N; ++i) { + if (!isfinite(f.v[i])) { + return false; + } + } + return true; +} + +// The jet is infinite if any part of the jet is infinite. +template inline +bool isinf(const Jet& f) { + if (isinf(f.a)) { + return true; + } + for (int i = 0; i < N; i++) { + if (isinf(f.v[i])) { + return true; + } + } + return false; +} + +// The jet is NaN if any part of the jet is NaN. +template inline +bool isnan(const Jet& f) { + if (isnan(f.a)) { + return true; + } + for (int i = 0; i < N; ++i) { + if (isnan(f.v[i])) { + return true; + } + } + return false; +} + +// The jet is normal if all parts of the jet are normal. +template inline +bool isnormal(const Jet& f) { + if (!isnormal(f.a)) { + return false; + } + for (int i = 0; i < N; ++i) { + if (!isnormal(f.v[i])) { + return false; + } + } + return true; +} + +// atan2(b + db, a + da) ~= atan2(b, a) + (- b da + a db) / (a^2 + b^2) +// +// In words: the rate of change of theta is 1/r times the rate of +// change of (x, y) in the positive angular direction. +template inline +Jet atan2(const Jet& g, const Jet& f) { + // Note order of arguments: + // + // f = a + da + // g = b + db + + Jet out; + + out.a = atan2(g.a, f.a); + + T const temp = T(1.0) / (f.a * f.a + g.a * g.a); + out.v = temp * (- g.a * f.v + f.a * g.v); + return out; +} + + +// pow -- base is a differentiatble function, exponent is a constant. +// (a+da)^p ~= a^p + p*a^(p-1) da +template inline +Jet pow(const Jet& f, double g) { + Jet out; + out.a = pow(f.a, g); + T const temp = g * pow(f.a, g - T(1.0)); + out.v = temp * f.v; + return out; +} + +// pow -- base is a constant, exponent is a differentiable function. +// (a)^(p+dp) ~= a^p + a^p log(a) dp +template inline +Jet pow(double f, const Jet& g) { + Jet out; + out.a = pow(f, g.a); + T const temp = log(f) * out.a; + out.v = temp * g.v; + return out; +} + + +// pow -- both base and exponent are differentiable functions. +// (a+da)^(b+db) ~= a^b + b * a^(b-1) da + a^b log(a) * db +template inline +Jet pow(const Jet& f, const Jet& g) { + Jet out; + + T const temp1 = pow(f.a, g.a); + T const temp2 = g.a * pow(f.a, g.a - T(1.0)); + T const temp3 = temp1 * log(f.a); + + out.a = temp1; + out.v = temp2 * f.v + temp3 * g.v; + return out; +} + +// Define the helper functions Eigen needs to embed Jet types. +// +// NOTE(keir): machine_epsilon() and precision() are missing, because they don't +// work with nested template types (e.g. where the scalar is itself templated). +// Among other things, this means that decompositions of Jet's does not work, +// for example +// +// Matrix ... > A, x, b; +// ... +// A.solve(b, &x) +// +// does not work and will fail with a strange compiler error. +// +// TODO(keir): This is an Eigen 2.0 limitation that is lifted in 3.0. When we +// switch to 3.0, also add the rest of the specialization functionality. +template inline const Jet& ei_conj(const Jet& x) { return x; } // NOLINT +template inline const Jet& ei_real(const Jet& x) { return x; } // NOLINT +template inline Jet ei_imag(const Jet& ) { return Jet(0.0); } // NOLINT +template inline Jet ei_abs (const Jet& x) { return fabs(x); } // NOLINT +template inline Jet ei_abs2(const Jet& x) { return x * x; } // NOLINT +template inline Jet ei_sqrt(const Jet& x) { return sqrt(x); } // NOLINT +template inline Jet ei_exp (const Jet& x) { return exp(x); } // NOLINT +template inline Jet ei_log (const Jet& x) { return log(x); } // NOLINT +template inline Jet ei_sin (const Jet& x) { return sin(x); } // NOLINT +template inline Jet ei_cos (const Jet& x) { return cos(x); } // NOLINT +template inline Jet ei_pow (const Jet& x, Jet y) { return pow(x, y); } // NOLINT + +// Note: This has to be in the ceres namespace for argument dependent lookup to +// function correctly. Otherwise statements like CHECK_LE(x, 2.0) fail with +// strange compile errors. +template +inline std::ostream &operator<<(std::ostream &s, const Jet& z) { + return s << "[" << z.a << " ; " << z.v.transpose() << "]"; +} + +} // namespace ceres + +namespace Eigen { + +// Creating a specialization of NumTraits enables placing Jet objects inside +// Eigen arrays, getting all the goodness of Eigen combined with autodiff. +template +struct NumTraits > { + typedef ceres::Jet Real; + typedef ceres::Jet NonInteger; + typedef ceres::Jet Nested; + + static typename ceres::Jet dummy_precision() { + return ceres::Jet(1e-12); + } + + enum { + IsComplex = 0, + IsInteger = 0, + IsSigned, + ReadCost = 1, + AddCost = 1, + // For Jet types, multiplication is more expensive than addition. + MulCost = 3, + HasFloatingPoint = 1 + }; +}; + +} // namespace Eigen + +#endif // CERES_PUBLIC_JET_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h b/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h new file mode 100644 index 00000000000..c0f7dc77a57 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h @@ -0,0 +1,189 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_ +#define CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { + +// Purpose: Sometimes parameter blocks x can overparameterize a problem +// +// min f(x) +// x +// +// In that case it is desirable to choose a parameterization for the +// block itself to remove the null directions of the cost. More +// generally, if x lies on a manifold of a smaller dimension than the +// ambient space that it is embedded in, then it is numerically and +// computationally more effective to optimize it using a +// parameterization that lives in the tangent space of that manifold +// at each point. +// +// For example, a sphere in three dimensions is a 2 dimensional +// manifold, embedded in a three dimensional space. At each point on +// the sphere, the plane tangent to it defines a two dimensional +// tangent space. For a cost function defined on this sphere, given a +// point x, moving in the direction normal to the sphere at that point +// is not useful. Thus a better way to do a local optimization is to +// optimize over two dimensional vector delta in the tangent space at +// that point and then "move" to the point x + delta, where the move +// operation involves projecting back onto the sphere. Doing so +// removes a redundent dimension from the optimization, making it +// numerically more robust and efficient. +// +// More generally we can define a function +// +// x_plus_delta = Plus(x, delta), +// +// where x_plus_delta has the same size as x, and delta is of size +// less than or equal to x. The function Plus, generalizes the +// definition of vector addition. Thus it satisfies the identify +// +// Plus(x, 0) = x, for all x. +// +// A trivial version of Plus is when delta is of the same size as x +// and +// +// Plus(x, delta) = x + delta +// +// A more interesting case if x is two dimensional vector, and the +// user wishes to hold the first coordinate constant. Then, delta is a +// scalar and Plus is defined as +// +// Plus(x, delta) = x + [0] * delta +// [1] +// +// An example that occurs commonly in Structure from Motion problems +// is when camera rotations are parameterized using Quaternion. There, +// it is useful only make updates orthogonal to that 4-vector defining +// the quaternion. One way to do this is to let delta be a 3 +// dimensional vector and define Plus to be +// +// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x +// +// The multiplication between the two 4-vectors on the RHS is the +// standard quaternion product. +// +// Given g and a point x, optimizing f can now be restated as +// +// min f(Plus(x, delta)) +// delta +// +// Given a solution delta to this problem, the optimal value is then +// given by +// +// x* = Plus(x, delta) +// +// The class LocalParameterization defines the function Plus and its +// Jacobian which is needed to compute the Jacobian of f w.r.t delta. +class LocalParameterization { + public: + virtual ~LocalParameterization() {} + + // Generalization of the addition operation, + // + // x_plus_delta = Plus(x, delta) + // + // with the condition that Plus(x, 0) = x. + virtual bool Plus(const double* x, + const double* delta, + double* x_plus_delta) const = 0; + + // The jacobian of Plus(x, delta) w.r.t delta at delta = 0. + virtual bool ComputeJacobian(const double* x, double* jacobian) const = 0; + + // Size of x. + virtual int GlobalSize() const = 0; + + // Size of delta. + virtual int LocalSize() const = 0; +}; + +// Some basic parameterizations + +// Identity Parameterization: Plus(x, delta) = x + delta +class IdentityParameterization : public LocalParameterization { + public: + explicit IdentityParameterization(int size); + virtual ~IdentityParameterization() {} + virtual bool Plus(const double* x, + const double* delta, + double* x_plus_delta) const; + virtual bool ComputeJacobian(const double* x, + double* jacobian) const; + virtual int GlobalSize() const { return size_; } + virtual int LocalSize() const { return size_; } + + private: + const int size_; +}; + +// Hold a subset of the parameters inside a parameter block constant. +class SubsetParameterization : public LocalParameterization { + public: + explicit SubsetParameterization(int size, + const vector& constant_parameters); + virtual ~SubsetParameterization() {} + virtual bool Plus(const double* x, + const double* delta, + double* x_plus_delta) const; + virtual bool ComputeJacobian(const double* x, + double* jacobian) const; + virtual int GlobalSize() const { return constancy_mask_.size(); } + virtual int LocalSize() const { return local_size_; } + + private: + const int local_size_; + vector constancy_mask_; +}; + +// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x +// with * being the quaternion multiplication operator. Here we assume +// that the first element of the quaternion vector is the real (cos +// theta) part. +class QuaternionParameterization : public LocalParameterization { + public: + virtual ~QuaternionParameterization() {} + virtual bool Plus(const double* x, + const double* delta, + double* x_plus_delta) const; + virtual bool ComputeJacobian(const double* x, + double* jacobian) const; + virtual int GlobalSize() const { return 4; } + virtual int LocalSize() const { return 3; } +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/loss_function.h b/extern/libmv/third_party/ceres/include/ceres/loss_function.h new file mode 100644 index 00000000000..81add02cdee --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/loss_function.h @@ -0,0 +1,322 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// The LossFunction interface is the way users describe how residuals +// are converted to cost terms for the overall problem cost function. +// For the exact manner in which loss functions are converted to the +// overall cost for a problem, see problem.h. +// +// For least squares problem where there are no outliers and standard +// squared loss is expected, it is not necessary to create a loss +// function; instead passing a NULL to the problem when adding +// residuals implies a standard squared loss. +// +// For least squares problems where the minimization may encounter +// input terms that contain outliers, that is, completely bogus +// measurements, it is important to use a loss function that reduces +// their associated penalty. +// +// Consider a structure from motion problem. The unknowns are 3D +// points and camera parameters, and the measurements are image +// coordinates describing the expected reprojected position for a +// point in a camera. For example, we want to model the geometry of a +// street scene with fire hydrants and cars, observed by a moving +// camera with unknown parameters, and the only 3D points we care +// about are the pointy tippy-tops of the fire hydrants. Our magic +// image processing algorithm, which is responsible for producing the +// measurements that are input to Ceres, has found and matched all +// such tippy-tops in all image frames, except that in one of the +// frame it mistook a car's headlight for a hydrant. If we didn't do +// anything special (i.e. if we used a basic quadratic loss), the +// residual for the erroneous measurement will result in extreme error +// due to the quadratic nature of squared loss. This results in the +// entire solution getting pulled away from the optimimum to reduce +// the large error that would otherwise be attributed to the wrong +// measurement. +// +// Using a robust loss function, the cost for large residuals is +// reduced. In the example above, this leads to outlier terms getting +// downweighted so they do not overly influence the final solution. +// +// What cost function is best? +// +// In general, there isn't a principled way to select a robust loss +// function. The authors suggest starting with a non-robust cost, then +// only experimenting with robust loss functions if standard squared +// loss doesn't work. + +#ifndef CERES_PUBLIC_LOSS_FUNCTION_H_ +#define CERES_PUBLIC_LOSS_FUNCTION_H_ + +#include +#include "ceres/internal/macros.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +class LossFunction { + public: + virtual ~LossFunction() {} + + // For a residual vector with squared 2-norm 'sq_norm', this method + // is required to fill in the value and derivatives of the loss + // function (rho in this example): + // + // out[0] = rho(sq_norm), + // out[1] = rho'(sq_norm), + // out[2] = rho''(sq_norm), + // + // Here the convention is that the contribution of a term to the + // cost function is given by 1/2 rho(s), where + // + // s = ||residuals||^2. + // + // Calling the method with a negative value of 's' is an error and + // the implementations are not required to handle that case. + // + // Most sane choices of rho() satisfy: + // + // rho(0) = 0, + // rho'(0) = 1, + // rho'(s) < 1 in outlier region, + // rho''(s) < 0 in outlier region, + // + // so that they mimic the least squares cost for small residuals. + virtual void Evaluate(double sq_norm, double out[3]) const = 0; +}; + +// Some common implementations follow below. +// +// Note: in the region of interest (i.e. s < 3) we have: +// TrivialLoss >= HuberLoss >= SoftLOneLoss >= CauchyLoss + + +// This corresponds to no robustification. +// +// rho(s) = s +// +// At s = 0: rho = [0, 1, 0]. +// +// It is not normally necessary to use this, as passing NULL for the +// loss function when building the problem accomplishes the same +// thing. +class TrivialLoss : public LossFunction { + public: + virtual void Evaluate(double, double*) const; +}; + +// Scaling +// ------- +// Given one robustifier +// s -> rho(s) +// one can change the length scale at which robustification takes +// place, by adding a scale factor 'a' as follows: +// +// s -> a^2 rho(s / a^2). +// +// The first and second derivatives are: +// +// s -> rho'(s / a^2), +// s -> (1 / a^2) rho''(s / a^2), +// +// but the behaviour near s = 0 is the same as the original function, +// i.e. +// +// rho(s) = s + higher order terms, +// a^2 rho(s / a^2) = s + higher order terms. +// +// The scalar 'a' should be positive. +// +// The reason for the appearance of squaring is that 'a' is in the +// units of the residual vector norm whereas 's' is a squared +// norm. For applications it is more convenient to specify 'a' than +// its square. The commonly used robustifiers below are described in +// un-scaled format (a = 1) but their implementations work for any +// non-zero value of 'a'. + +// Huber. +// +// rho(s) = s for s <= 1, +// rho(s) = 2 sqrt(s) - 1 for s >= 1. +// +// At s = 0: rho = [0, 1, 0]. +// +// The scaling parameter 'a' corresponds to 'delta' on this page: +// http://en.wikipedia.org/wiki/Huber_Loss_Function +class HuberLoss : public LossFunction { + public: + explicit HuberLoss(double a) : a_(a), b_(a * a) { } + virtual void Evaluate(double, double*) const; + private: + const double a_; + // b = a^2. + const double b_; +}; + +// Soft L1, similar to Huber but smooth. +// +// rho(s) = 2 (sqrt(1 + s) - 1). +// +// At s = 0: rho = [0, 1, -1/2]. +class SoftLOneLoss : public LossFunction { + public: + explicit SoftLOneLoss(double a) : b_(a * a), c_(1 / b_) { } + virtual void Evaluate(double, double*) const; + private: + // b = a^2. + const double b_; + // c = 1 / a^2. + const double c_; +}; + +// Inspired by the Cauchy distribution +// +// rho(s) = log(1 + s). +// +// At s = 0: rho = [0, 1, -1]. +class CauchyLoss : public LossFunction { + public: + explicit CauchyLoss(double a) : b_(a * a), c_(1 / b_) { } + virtual void Evaluate(double, double*) const; + private: + // b = a^2. + const double b_; + // c = 1 / a^2. + const double c_; +}; + +// The discussion above has to do with length scaling: it affects the space +// in which s is measured. Sometimes you want to simply scale the output +// value of the robustifier. For example, you might want to weight +// different error terms differently (e.g., weight pixel reprojection +// errors differently from terrain errors). +// +// If rho is the wrapped robustifier, then this simply outputs +// s -> a * rho(s) +// +// The first and second derivatives are, not surprisingly +// s -> a * rho'(s) +// s -> a * rho''(s) +// +// Since we treat the a NULL Loss function as the Identity loss +// function, rho = NULL is a valid input and will result in the input +// being scaled by a. This provides a simple way of implementing a +// scaled ResidualBlock. +class ScaledLoss : public LossFunction { + public: + // Constructs a ScaledLoss wrapping another loss function. Takes + // ownership of the wrapped loss function or not depending on the + // ownership parameter. + ScaledLoss(const LossFunction* rho, double a, Ownership ownership) : + rho_(rho), a_(a), ownership_(ownership) { } + + virtual ~ScaledLoss() { + if (ownership_ == DO_NOT_TAKE_OWNERSHIP) { + rho_.release(); + } + } + virtual void Evaluate(double, double*) const; + + private: + internal::scoped_ptr rho_; + const double a_; + const Ownership ownership_; + DISALLOW_COPY_AND_ASSIGN(ScaledLoss); +}; + +// Sometimes after the optimization problem has been constructed, we +// wish to mutate the scale of the loss function. For example, when +// performing estimation from data which has substantial outliers, +// convergence can be improved by starting out with a large scale, +// optimizing the problem and then reducing the scale. This can have +// better convergence behaviour than just using a loss function with a +// small scale. +// +// This templated class allows the user to implement a loss function +// whose scale can be mutated after an optimization problem has been +// constructed. +// +// Example usage +// +// Problem problem; +// +// // Add parameter blocks +// +// CostFunction* cost_function = +// new AutoDiffCostFunction < UW_Camera_Mapper, 2, 9, 3>( +// new UW_Camera_Mapper(data->observations[2*i + 0], +// data->observations[2*i + 1])); +// +// LossFunctionWrapper* loss_function(new HuberLoss(1.0), TAKE_OWNERSHIP); +// +// problem.AddResidualBlock(cost_function, loss_function, parameters); +// +// Solver::Options options; +// scoped_ptr summary1(Solve(problem, options)); +// +// loss_function->Reset(new HuberLoss(1.0), TAKE_OWNERSHIP); +// +// scoped_ptr summary2(Solve(problem, options)); +// +class LossFunctionWrapper : public LossFunction { + public: + LossFunctionWrapper(LossFunction* rho, Ownership ownership) + : rho_(rho), ownership_(ownership) { + } + + virtual ~LossFunctionWrapper() { + if (ownership_ == DO_NOT_TAKE_OWNERSHIP) { + rho_.release(); + } + } + + virtual void Evaluate(double sq_norm, double out[3]) const { + CHECK_NOTNULL(rho_.get()); + rho_->Evaluate(sq_norm, out); + } + + void Reset(LossFunction* rho, Ownership ownership) { + if (ownership_ == DO_NOT_TAKE_OWNERSHIP) { + rho_.release(); + } + rho_.reset(rho); + ownership_ = ownership; + } + + private: + internal::scoped_ptr rho_; + Ownership ownership_; + DISALLOW_COPY_AND_ASSIGN(LossFunctionWrapper); +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_LOSS_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/normal_prior.h b/extern/libmv/third_party/ceres/include/ceres/normal_prior.h new file mode 100644 index 00000000000..480a07474a7 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/normal_prior.h @@ -0,0 +1,75 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Cost term that implements a prior on a parameter block using a +// normal distribution. + +#ifndef CERES_PUBLIC_NORMAL_PRIOR_H_ +#define CERES_PUBLIC_NORMAL_PRIOR_H_ + +#include "ceres/cost_function.h" +#include "ceres/internal/eigen.h" + +namespace ceres { + +// Implements a cost function of the form +// +// cost(x) = ||A(x - b)||^2 +// +// where, the matrix A and the vector b are fixed and x is the +// variable. In case the user is interested in implementing a cost +// function of the form +// +// cost(x) = (x - mu)^T S^{-1} (x - mu) +// +// where, mu is a vector and S is a covariance matrix, then, A = +// S^{-1/2}, i.e the matrix A is the square root of the inverse of the +// covariance, also known as the stiffness matrix. There are however +// no restrictions on the shape of A. It is free to be rectangular, +// which would be the case if the covariance matrix S is rank +// deficient. + +class NormalPrior: public CostFunction { + public: + // Check that the number of rows in the vector b are the same as the + // number of columns in the matrix A, crash otherwise. + NormalPrior(const Matrix& A, const Vector& b); + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const; + private: + Matrix A_; + Vector b_; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_NORMAL_PRIOR_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h new file mode 100644 index 00000000000..bbaefca5b6c --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h @@ -0,0 +1,283 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Create CostFunctions as needed by the least squares framework with jacobians +// computed via numeric (a.k.a. finite) differentiation. For more details see +// http://en.wikipedia.org/wiki/Numerical_differentiation. +// +// To get a numerically differentiated cost function, define a subclass of +// CostFunction such that the Evaluate() function ignores the jacobian +// parameter. The numeric differentiation wrapper will fill in the jacobian +// parameter if nececssary by repeatedly calling the Evaluate() function with +// small changes to the appropriate parameters, and computing the slope. For +// performance, the numeric differentiation wrapper class is templated on the +// concrete cost function, even though it could be implemented only in terms of +// the virtual CostFunction interface. +// +// The numerically differentiated version of a cost function for a cost function +// can be constructed as follows: +// +// CostFunction* cost_function +// = new NumericDiffCostFunction( +// new MyCostFunction(...), TAKE_OWNERSHIP); +// +// where MyCostFunction has 1 residual and 2 parameter blocks with sizes 4 and 8 +// respectively. Look at the tests for a more detailed example. +// +// The central difference method is considerably more accurate at the cost of +// twice as many function evaluations than forward difference. Consider using +// central differences begin with, and only after that works, trying forward +// difference to improve performance. +// +// TODO(keir): Characterize accuracy; mention pitfalls; provide alternatives. + +#ifndef CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_ +#define CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_ + +#include +#include +#include "Eigen/Dense" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/sized_cost_function.h" +#include "ceres/types.h" + +namespace ceres { + +enum NumericDiffMethod { + CENTRAL, + FORWARD +}; + +// This is split from the main class because C++ doesn't allow partial template +// specializations for member functions. The alternative is to repeat the main +// class for differing numbers of parameters, which is also unfortunate. +template +struct Differencer { + // Mutates parameters but must restore them before return. + static bool EvaluateJacobianForParameterBlock( + const CostFunctionNoJacobian *function, + double const* residuals_at_eval_point, + double **parameters, + double **jacobians) { + using Eigen::Map; + using Eigen::Matrix; + using Eigen::RowMajor; + + typedef Matrix ResidualVector; + typedef Matrix ParameterVector; + typedef Matrix + JacobianMatrix; + + Map parameter_jacobian(jacobians[parameter_block], + num_residuals, + parameter_block_size); + + // Mutate 1 element at a time and then restore. + Map x_plus_delta(parameters[parameter_block], + parameter_block_size); + ParameterVector x(x_plus_delta); + + // TODO(keir): Pick a smarter number! In theory a good choice is sqrt(eps) * + // x, which for doubles means about 1e-8 * x. However, I have found this + // number too optimistic. This number should be exposed for users to change. + const double kRelativeStepSize = 1e-6; + + ParameterVector step_size = x.array().abs() * kRelativeStepSize; + + // To handle cases where a parameter is exactly zero, instead use the mean + // step_size for the other dimensions. + double fallback_step_size = step_size.sum() / step_size.rows(); + if (fallback_step_size == 0.0) { + // If all the parameters are zero, there's no good answer. Take + // kRelativeStepSize as a guess and hope for the best. + fallback_step_size = kRelativeStepSize; + } + + // For each parameter in the parameter block, use finite differences to + // compute the derivative for that parameter. + for (int j = 0; j < parameter_block_size; ++j) { + if (step_size(j) == 0.0) { + // The parameter is exactly zero, so compromise and use the mean + // step_size from the other parameters. This can break in many cases, + // but it's hard to pick a good number without problem specific + // knowledge. + step_size(j) = fallback_step_size; + } + x_plus_delta(j) = x(j) + step_size(j); + + double residuals[num_residuals]; // NOLINT + if (!function->Evaluate(parameters, residuals, NULL)) { + // Something went wrong; bail. + return false; + } + + // Compute this column of the jacobian in 3 steps: + // 1. Store residuals for the forward part. + // 2. Subtract residuals for the backward (or 0) part. + // 3. Divide out the run. + parameter_jacobian.col(j) = + Map(residuals, num_residuals); + + double one_over_h = 1 / step_size(j); + if (method == CENTRAL) { + // Compute the function on the other side of x(j). + x_plus_delta(j) = x(j) - step_size(j); + + if (!function->Evaluate(parameters, residuals, NULL)) { + // Something went wrong; bail. + return false; + } + parameter_jacobian.col(j) -= + Map(residuals, num_residuals, 1); + one_over_h /= 2; + } else { + // Forward difference only; reuse existing residuals evaluation. + parameter_jacobian.col(j) -= + Map(residuals_at_eval_point, num_residuals); + } + x_plus_delta(j) = x(j); // Restore x_plus_delta. + + // Divide out the run to get slope. + parameter_jacobian.col(j) *= one_over_h; + } + return true; + } +}; + +// Prevent invalid instantiations. +template +struct Differencer { + static bool EvaluateJacobianForParameterBlock( + const CostFunctionNoJacobian *function, + double const* residuals_at_eval_point, + double **parameters, + double **jacobians) { + LOG(FATAL) << "Shouldn't get here."; + return true; + } +}; + +template +class NumericDiffCostFunction + : public SizedCostFunction { + public: + NumericDiffCostFunction(CostFunctionNoJacobian* function, + Ownership ownership) + : function_(function), ownership_(ownership) {} + + virtual ~NumericDiffCostFunction() { + if (ownership_ != TAKE_OWNERSHIP) { + function_.release(); + } + } + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + // Get the function value (residuals) at the the point to evaluate. + bool success = function_->Evaluate(parameters, residuals, NULL); + if (!success) { + // Something went wrong; ignore the jacobian. + return false; + } + if (!jacobians) { + // Nothing to do; just forward. + return true; + } + + // Create a copy of the parameters which will get mutated. + const int kParametersSize = N0 + N1 + N2 + N3 + N4 + N5; + double parameters_copy[kParametersSize]; + double *parameters_references_copy[6]; + parameters_references_copy[0] = ¶meters_copy[0]; + parameters_references_copy[1] = ¶meters_copy[0] + N0; + parameters_references_copy[2] = ¶meters_copy[0] + N0 + N1; + parameters_references_copy[3] = ¶meters_copy[0] + N0 + N1 + N2; + parameters_references_copy[4] = ¶meters_copy[0] + N0 + N1 + N2 + N3; + parameters_references_copy[5] = + ¶meters_copy[0] + N0 + N1 + N2 + N3 + N4; + +#define COPY_PARAMETER_BLOCK(block) \ + if (N ## block) memcpy(parameters_references_copy[block], \ + parameters[block], \ + sizeof(double) * N ## block); // NOLINT + COPY_PARAMETER_BLOCK(0); + COPY_PARAMETER_BLOCK(1); + COPY_PARAMETER_BLOCK(2); + COPY_PARAMETER_BLOCK(3); + COPY_PARAMETER_BLOCK(4); + COPY_PARAMETER_BLOCK(5); +#undef COPY_PARAMETER_BLOCK + +#define EVALUATE_JACOBIAN_FOR_BLOCK(block) \ + if (N ## block && jacobians[block]) { \ + if (!Differencer::EvaluateJacobianForParameterBlock( \ + function_.get(), \ + residuals, \ + parameters_references_copy, \ + jacobians)) { \ + return false; \ + } \ + } + EVALUATE_JACOBIAN_FOR_BLOCK(0); + EVALUATE_JACOBIAN_FOR_BLOCK(1); + EVALUATE_JACOBIAN_FOR_BLOCK(2); + EVALUATE_JACOBIAN_FOR_BLOCK(3); + EVALUATE_JACOBIAN_FOR_BLOCK(4); + EVALUATE_JACOBIAN_FOR_BLOCK(5); +#undef EVALUATE_JACOBIAN_FOR_BLOCK + return true; + } + + private: + internal::scoped_ptr function_; + Ownership ownership_; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/problem.h b/extern/libmv/third_party/ceres/include/ceres/problem.h new file mode 100644 index 00000000000..0ca61006bdb --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/problem.h @@ -0,0 +1,265 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) +// +// The Problem object is used to build and hold least squares problems. + +#ifndef CERES_PUBLIC_PROBLEM_H_ +#define CERES_PUBLIC_PROBLEM_H_ + +#include +#include +#include +#include + +#include +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +class CostFunction; +class LossFunction; +class LocalParameterization; + +namespace internal { +class Preprocessor; +class ProblemImpl; +class ParameterBlock; +class ResidualBlock; +class SolverImpl; +} // namespace internal + +// A ResidualBlockId is a handle clients can use to delete residual +// blocks after creating them. They are opaque for any purposes other +// than that. +typedef const internal::ResidualBlock* ResidualBlockId; + +// A class to represent non-linear least squares problems. Such +// problems have a cost function that is a sum of error terms (known +// as "residuals"), where each residual is a function of some subset +// of the parameters. The cost function takes the form +// +// N 1 +// SUM --- loss( || r_i1, r_i2,..., r_ik ||^2 ), +// i=1 2 +// +// where +// +// r_ij is residual number i, component j; the residual is a +// function of some subset of the parameters x1...xk. For +// example, in a structure from motion problem a residual +// might be the difference between a measured point in an +// image and the reprojected position for the matching +// camera, point pair. The residual would have two +// components, error in x and error in y. +// +// loss(y) is the loss function; for example, squared error or +// Huber L1 loss. If loss(y) = y, then the cost function is +// non-robustified least squares. +// +// This class is specifically designed to address the important subset +// of "sparse" least squares problems, where each component of the +// residual depends only on a small number number of parameters, even +// though the total number of residuals and parameters may be very +// large. This property affords tremendous gains in scale, allowing +// efficient solving of large problems that are otherwise +// inaccessible. +// +// The canonical example of a sparse least squares problem is +// "structure-from-motion" (SFM), where the parameters are points and +// cameras, and residuals are reprojection errors. Typically a single +// residual will depend only on 9 parameters (3 for the point, 6 for +// the camera). +// +// To create a least squares problem, use the AddResidualBlock() and +// AddParameterBlock() methods, documented below. Here is an example least +// squares problem containing 3 parameter blocks of sizes 3, 4 and 5 +// respectively and two residual terms of size 2 and 6: +// +// double x1[] = { 1.0, 2.0, 3.0 }; +// double x2[] = { 1.0, 2.0, 3.0, 5.0 }; +// double x3[] = { 1.0, 2.0, 3.0, 6.0, 7.0 }; +// +// Problem problem; +// +// problem.AddResidualBlock(new MyUnaryCostFunction(...), x1); +// problem.AddResidualBlock(new MyBinaryCostFunction(...), x2, x3); +// +// Please see cost_function.h for details of the CostFunction object. +class Problem { + public: + struct Options { + Options() + : cost_function_ownership(TAKE_OWNERSHIP), + loss_function_ownership(TAKE_OWNERSHIP), + local_parameterization_ownership(TAKE_OWNERSHIP) {} + + // These flags control whether the Problem object owns the cost + // functions, loss functions, and parameterizations passed into + // the Problem. If set to TAKE_OWNERSHIP, then the problem object + // will delete the corresponding cost or loss functions on + // destruction. The destructor is careful to delete the pointers + // only once, since sharing cost/loss/parameterizations is + // allowed. + Ownership cost_function_ownership; + Ownership loss_function_ownership; + Ownership local_parameterization_ownership; + }; + + // The default constructor is equivalent to the + // invocation Problem(Problem::Options()). + Problem(); + explicit Problem(const Options& options); + + ~Problem(); + + // Add a residual block to the overall cost function. The cost + // function carries with it information about the sizes of the + // parameter blocks it expects. The function checks that these match + // the sizes of the parameter blocks listed in parameter_blocks. The + // program aborts if a mismatch is detected. loss_function can be + // NULL, in which case the cost of the term is just the squared norm + // of the residuals. + // + // The user has the option of explicitly adding the parameter blocks + // using AddParameterBlock. This causes additional correctness + // checking; however, AddResidualBlock implicitly adds the parameter + // blocks if they are not present, so calling AddParameterBlock + // explicitly is not required. + // + // The Problem object by default takes ownership of the + // cost_function and loss_function pointers. These objects remain + // live for the life of the Problem object. If the user wishes to + // keep control over the destruction of these objects, then they can + // do this by setting the corresponding enums in the Options struct. + // + // Note: Even though the Problem takes ownership of cost_function + // and loss_function, it does not preclude the user from re-using + // them in another residual block. The destructor takes care to call + // delete on each cost_function or loss_function pointer only once, + // regardless of how many residual blocks refer to them. + // + // Example usage: + // + // double x1[] = {1.0, 2.0, 3.0}; + // double x2[] = {1.0, 2.0, 5.0, 6.0}; + // double x3[] = {3.0, 6.0, 2.0, 5.0, 1.0}; + // + // Problem problem; + // + // problem.AddResidualBlock(new MyUnaryCostFunction(...), NULL, x1); + // problem.AddResidualBlock(new MyBinaryCostFunction(...), NULL, x2, x1); + // + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + const vector& parameter_blocks); + + // Convenience methods for adding residuals with a small number of + // parameters. This is the common case. Instead of specifying the + // parameter block arguments as a vector, list them as pointers. + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3, double* x4); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3, double* x4, double* x5); + + // Add a parameter block with appropriate size to the problem. + // Repeated calls with the same arguments are ignored. Repeated + // calls with the same double pointer but a different size results + // in undefined behaviour. + void AddParameterBlock(double* values, int size); + + // Add a parameter block with appropriate size and parameterization + // to the problem. Repeated calls with the same arguments are + // ignored. Repeated calls with the same double pointer but a + // different size results in undefined behaviour. + void AddParameterBlock(double* values, + int size, + LocalParameterization* local_parameterization); + + // Hold the indicated parameter block constant during optimization. + void SetParameterBlockConstant(double* values); + + // Allow the indicated parameter to vary during optimization. + void SetParameterBlockVariable(double* values); + + // Set the local parameterization for one of the parameter blocks. + // The local_parameterization is owned by the Problem by default. It + // is acceptable to set the same parameterization for multiple + // parameters; the destructor is careful to delete local + // parameterizations only once. The local parameterization can only + // be set once per parameter, and cannot be changed once set. + void SetParameterization(double* values, + LocalParameterization* local_parameterization); + + // Number of parameter blocks in the problem. Always equals + // parameter_blocks().size() and parameter_block_sizes().size(). + int NumParameterBlocks() const; + + // The size of the parameter vector obtained by summing over the + // sizes of all the parameter blocks. + int NumParameters() const; + + // Number of residual blocks in the problem. Always equals + // residual_blocks().size(). + int NumResidualBlocks() const; + + // The size of the residual vector obtained by summing over the + // sizes of all of the residual blocks. + int NumResiduals() const; + + private: + friend class internal::SolverImpl; + internal::scoped_ptr problem_impl_; + DISALLOW_COPY_AND_ASSIGN(Problem); +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_PROBLEM_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/rotation.h b/extern/libmv/third_party/ceres/include/ceres/rotation.h new file mode 100644 index 00000000000..e4227e78b9a --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/rotation.h @@ -0,0 +1,526 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// sameeragarwal@google.com (Sameer Agarwal) +// +// Templated functions for manipulating rotations. The templated +// functions are useful when implementing functors for automatic +// differentiation. +// +// In the following, the Quaternions are laid out as 4-vectors, thus: +// +// q[0] scalar part. +// q[1] coefficient of i. +// q[2] coefficient of j. +// q[3] coefficient of k. +// +// where: i*i = j*j = k*k = -1 and i*j = k, j*k = i, k*i = j. + +#ifndef CERES_PUBLIC_ROTATION_H_ +#define CERES_PUBLIC_ROTATION_H_ + +#include +#include + +namespace ceres { + +// Convert a value in combined axis-angle representation to a quaternion. +// The value angle_axis is a triple whose norm is an angle in radians, +// and whose direction is aligned with the axis of rotation, +// and quaternion is a 4-tuple that will contain the resulting quaternion. +// The implementation may be used with auto-differentiation up to the first +// derivative, higher derivatives may have unexpected results near the origin. +template +void AngleAxisToQuaternion(T const* angle_axis, T* quaternion); + +// Convert a quaternion to the equivalent combined axis-angle representation. +// The value quaternion must be a unit quaternion - it is not normalized first, +// and angle_axis will be filled with a value whose norm is the angle of +// rotation in radians, and whose direction is the axis of rotation. +// The implemention may be used with auto-differentiation up to the first +// derivative, higher derivatives may have unexpected results near the origin. +template +void QuaternionToAngleAxis(T const* quaternion, T* angle_axis); + +// Conversions between 3x3 rotation matrix (in column major order) and +// axis-angle rotation representations. Templated for use with +// autodifferentiation. +template +void RotationMatrixToAngleAxis(T const * R, T * angle_axis); +template +void AngleAxisToRotationMatrix(T const * angle_axis, T * R); + +// Conversions between 3x3 rotation matrix (in row major order) and +// Euler angle (in degrees) rotation representations. +// +// The {pitch,roll,yaw} Euler angles are rotations around the {x,y,z} +// axes, respectively. They are applied in that same order, so the +// total rotation R is Rz * Ry * Rx. +template +void EulerAnglesToRotationMatrix(const T* euler, int row_stride, T* R); + +// Convert a 4-vector to a 3x3 scaled rotation matrix. +// +// The choice of rotation is such that the quaternion [1 0 0 0] goes to an +// identity matrix and for small a, b, c the quaternion [1 a b c] goes to +// the matrix +// +// [ 0 -c b ] +// I + 2 [ c 0 -a ] + higher order terms +// [ -b a 0 ] +// +// which corresponds to a Rodrigues approximation, the last matrix being +// the cross-product matrix of [a b c]. Together with the property that +// R(q1 * q2) = R(q1) * R(q2) this uniquely defines the mapping from q to R. +// +// The rotation matrix is row-major. +// +// No normalization of the quaternion is performed, i.e. +// R = ||q||^2 * Q, where Q is an orthonormal matrix +// such that det(Q) = 1 and Q*Q' = I +template inline +void QuaternionToScaledRotation(const T q[4], T R[3 * 3]); + +// Same as above except that the rotation matrix is normalized by the +// Frobenius norm, so that R * R' = I (and det(R) = 1). +template inline +void QuaternionToRotation(const T q[4], T R[3 * 3]); + +// Rotates a point pt by a quaternion q: +// +// result = R(q) * pt +// +// Assumes the quaternion is unit norm. This assumption allows us to +// write the transform as (something)*pt + pt, as is clear from the +// formula below. If you pass in a quaternion with |q|^2 = 2 then you +// WILL NOT get back 2 times the result you get for a unit quaternion. +template inline +void UnitQuaternionRotatePoint(const T q[4], const T pt[3], T result[3]); + +// With this function you do not need to assume that q has unit norm. +// It does assume that the norm is non-zero. +template inline +void QuaternionRotatePoint(const T q[4], const T pt[3], T result[3]); + +// zw = z * w, where * is the Quaternion product between 4 vectors. +template inline +void QuaternionProduct(const T z[4], const T w[4], T zw[4]); + +// xy = x cross y; +template inline +void CrossProduct(const T x[3], const T y[3], T x_cross_y[3]); + +template inline +T DotProduct(const T x[3], const T y[3]); + +// y = R(angle_axis) * x; +template inline +void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]); + +// --- IMPLEMENTATION + +// Duplicate rather than decorate every use of cmath with _USE_MATH_CONSTANTS. +// Necessitated by Windows. +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#define CERES_NEED_M_PI_UNDEF +#endif + +template +inline void AngleAxisToQuaternion(const T* angle_axis, T* quaternion) { + const T &a0 = angle_axis[0]; + const T &a1 = angle_axis[1]; + const T &a2 = angle_axis[2]; + const T theta_squared = a0 * a0 + a1 * a1 + a2 * a2; + + // For points not at the origin, the full conversion is numerically stable. + if (theta_squared > T(0.0)) { + const T theta = sqrt(theta_squared); + const T half_theta = theta * T(0.5); + const T k = sin(half_theta) / theta; + quaternion[0] = cos(half_theta); + quaternion[1] = a0 * k; + quaternion[2] = a1 * k; + quaternion[3] = a2 * k; + } else { + // At the origin, sqrt() will produce NaN in the derivative since + // the argument is zero. By approximating with a Taylor series, + // and truncating at one term, the value and first derivatives will be + // computed correctly when Jets are used. + const T k(0.5); + quaternion[0] = T(1.0); + quaternion[1] = a0 * k; + quaternion[2] = a1 * k; + quaternion[3] = a2 * k; + } +} + +template +inline void QuaternionToAngleAxis(const T* quaternion, T* angle_axis) { + const T &q1 = quaternion[1]; + const T &q2 = quaternion[2]; + const T &q3 = quaternion[3]; + const T sin_squared = q1 * q1 + q2 * q2 + q3 * q3; + + // For quaternions representing non-zero rotation, the conversion + // is numerically stable. + if (sin_squared > T(0.0)) { + const T sin_theta = sqrt(sin_squared); + const T k = T(2.0) * atan2(sin_theta, quaternion[0]) / sin_theta; + angle_axis[0] = q1 * k; + angle_axis[1] = q2 * k; + angle_axis[2] = q3 * k; + } else { + // For zero rotation, sqrt() will produce NaN in the derivative since + // the argument is zero. By approximating with a Taylor series, + // and truncating at one term, the value and first derivatives will be + // computed correctly when Jets are used. + const T k(2.0); + angle_axis[0] = q1 * k; + angle_axis[1] = q2 * k; + angle_axis[2] = q3 * k; + } +} + +// The conversion of a rotation matrix to the angle-axis form is +// numerically problematic when then rotation angle is close to zero +// or to Pi. The following implementation detects when these two cases +// occurs and deals with them by taking code paths that are guaranteed +// to not perform division by a small number. +template +inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) { + // x = k * 2 * sin(theta), where k is the axis of rotation. + angle_axis[0] = R[5] - R[7]; + angle_axis[1] = R[6] - R[2]; + angle_axis[2] = R[1] - R[3]; + + static const T kOne = T(1.0); + static const T kTwo = T(2.0); + + // Since the right hand side may give numbers just above 1.0 or + // below -1.0 leading to atan misbehaving, we threshold. + T costheta = std::min(std::max((R[0] + R[4] + R[8] - kOne) / kTwo, + T(-1.0)), + kOne); + + // sqrt is guaranteed to give non-negative results, so we only + // threshold above. + T sintheta = std::min(sqrt(angle_axis[0] * angle_axis[0] + + angle_axis[1] * angle_axis[1] + + angle_axis[2] * angle_axis[2]) / kTwo, + kOne); + + // Use the arctan2 to get the right sign on theta + const T theta = atan2(sintheta, costheta); + + // Case 1: sin(theta) is large enough, so dividing by it is not a + // problem. We do not use abs here, because while jets.h imports + // std::abs into the namespace, here in this file, abs resolves to + // the int version of the function, which returns zero always. + // + // We use a threshold much larger then the machine epsilon, because + // if sin(theta) is small, not only do we risk overflow but even if + // that does not occur, just dividing by a small number will result + // in numerical garbage. So we play it safe. + static const double kThreshold = 1e-12; + if ((sintheta > kThreshold) || (sintheta < -kThreshold)) { + const T r = theta / (kTwo * sintheta); + for (int i = 0; i < 3; ++i) { + angle_axis[i] *= r; + } + return; + } + + // Case 2: theta ~ 0, means sin(theta) ~ theta to a good + // approximation. + if (costheta > 0) { + const T kHalf = T(0.5); + for (int i = 0; i < 3; ++i) { + angle_axis[i] *= kHalf; + } + return; + } + + // Case 3: theta ~ pi, this is the hard case. Since theta is large, + // and sin(theta) is small. Dividing by theta by sin(theta) will + // either give an overflow or worse still numerically meaningless + // results. Thus we use an alternate more complicated formula + // here. + + // Since cos(theta) is negative, division by (1-cos(theta)) cannot + // overflow. + const T inv_one_minus_costheta = kOne / (kOne - costheta); + + // We now compute the absolute value of coordinates of the axis + // vector using the diagonal entries of R. To resolve the sign of + // these entries, we compare the sign of angle_axis[i]*sin(theta) + // with the sign of sin(theta). If they are the same, then + // angle_axis[i] should be positive, otherwise negative. + for (int i = 0; i < 3; ++i) { + angle_axis[i] = theta * sqrt((R[i*4] - costheta) * inv_one_minus_costheta); + if (((sintheta < 0) && (angle_axis[i] > 0)) || + ((sintheta > 0) && (angle_axis[i] < 0))) { + angle_axis[i] = -angle_axis[i]; + } + } +} + +template +inline void AngleAxisToRotationMatrix(const T * angle_axis, T * R) { + static const T kOne = T(1.0); + const T theta2 = DotProduct(angle_axis, angle_axis); + if (theta2 > 0.0) { + // We want to be careful to only evaluate the square root if the + // norm of the angle_axis vector is greater than zero. Otherwise + // we get a division by zero. + const T theta = sqrt(theta2); + const T wx = angle_axis[0] / theta; + const T wy = angle_axis[1] / theta; + const T wz = angle_axis[2] / theta; + + const T costheta = cos(theta); + const T sintheta = sin(theta); + + R[0] = costheta + wx*wx*(kOne - costheta); + R[1] = wz*sintheta + wx*wy*(kOne - costheta); + R[2] = -wy*sintheta + wx*wz*(kOne - costheta); + R[3] = wx*wy*(kOne - costheta) - wz*sintheta; + R[4] = costheta + wy*wy*(kOne - costheta); + R[5] = wx*sintheta + wy*wz*(kOne - costheta); + R[6] = wy*sintheta + wx*wz*(kOne - costheta); + R[7] = -wx*sintheta + wy*wz*(kOne - costheta); + R[8] = costheta + wz*wz*(kOne - costheta); + } else { + // At zero, we switch to using the first order Taylor expansion. + R[0] = kOne; + R[1] = -angle_axis[2]; + R[2] = angle_axis[1]; + R[3] = angle_axis[2]; + R[4] = kOne; + R[5] = -angle_axis[0]; + R[6] = -angle_axis[1]; + R[7] = angle_axis[0]; + R[8] = kOne; + } +} + +template +inline void EulerAnglesToRotationMatrix(const T* euler, + const int row_stride, + T* R) { + const T degrees_to_radians(M_PI / 180.0); + + const T pitch(euler[0] * degrees_to_radians); + const T roll(euler[1] * degrees_to_radians); + const T yaw(euler[2] * degrees_to_radians); + + const T c1 = cos(yaw); + const T s1 = sin(yaw); + const T c2 = cos(roll); + const T s2 = sin(roll); + const T c3 = cos(pitch); + const T s3 = sin(pitch); + + // Rows of the rotation matrix. + T* R1 = R; + T* R2 = R1 + row_stride; + T* R3 = R2 + row_stride; + + R1[0] = c1*c2; + R1[1] = -s1*c3 + c1*s2*s3; + R1[2] = s1*s3 + c1*s2*c3; + + R2[0] = s1*c2; + R2[1] = c1*c3 + s1*s2*s3; + R2[2] = -c1*s3 + s1*s2*c3; + + R3[0] = -s2; + R3[1] = c2*s3; + R3[2] = c2*c3; +} + +template inline +void QuaternionToScaledRotation(const T q[4], T R[3 * 3]) { + // Make convenient names for elements of q. + T a = q[0]; + T b = q[1]; + T c = q[2]; + T d = q[3]; + // This is not to eliminate common sub-expression, but to + // make the lines shorter so that they fit in 80 columns! + T aa = a * a; + T ab = a * b; + T ac = a * c; + T ad = a * d; + T bb = b * b; + T bc = b * c; + T bd = b * d; + T cc = c * c; + T cd = c * d; + T dd = d * d; + + R[0] = aa + bb - cc - dd; R[1] = T(2) * (bc - ad); R[2] = T(2) * (ac + bd); // NOLINT + R[3] = T(2) * (ad + bc); R[4] = aa - bb + cc - dd; R[5] = T(2) * (cd - ab); // NOLINT + R[6] = T(2) * (bd - ac); R[7] = T(2) * (ab + cd); R[8] = aa - bb - cc + dd; // NOLINT +} + +template inline +void QuaternionToRotation(const T q[4], T R[3 * 3]) { + QuaternionToScaledRotation(q, R); + + T normalizer = q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]; + CHECK_NE(normalizer, T(0)); + normalizer = T(1) / normalizer; + + for (int i = 0; i < 9; ++i) { + R[i] *= normalizer; + } +} + +template inline +void UnitQuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) { + const T t2 = q[0] * q[1]; + const T t3 = q[0] * q[2]; + const T t4 = q[0] * q[3]; + const T t5 = -q[1] * q[1]; + const T t6 = q[1] * q[2]; + const T t7 = q[1] * q[3]; + const T t8 = -q[2] * q[2]; + const T t9 = q[2] * q[3]; + const T t1 = -q[3] * q[3]; + result[0] = T(2) * ((t8 + t1) * pt[0] + (t6 - t4) * pt[1] + (t3 + t7) * pt[2]) + pt[0]; // NOLINT + result[1] = T(2) * ((t4 + t6) * pt[0] + (t5 + t1) * pt[1] + (t9 - t2) * pt[2]) + pt[1]; // NOLINT + result[2] = T(2) * ((t7 - t3) * pt[0] + (t2 + t9) * pt[1] + (t5 + t8) * pt[2]) + pt[2]; // NOLINT +} + + +template inline +void QuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) { + // 'scale' is 1 / norm(q). + const T scale = T(1) / sqrt(q[0] * q[0] + + q[1] * q[1] + + q[2] * q[2] + + q[3] * q[3]); + + // Make unit-norm version of q. + const T unit[4] = { + scale * q[0], + scale * q[1], + scale * q[2], + scale * q[3], + }; + + UnitQuaternionRotatePoint(unit, pt, result); +} + +template inline +void QuaternionProduct(const T z[4], const T w[4], T zw[4]) { + zw[0] = z[0] * w[0] - z[1] * w[1] - z[2] * w[2] - z[3] * w[3]; + zw[1] = z[0] * w[1] + z[1] * w[0] + z[2] * w[3] - z[3] * w[2]; + zw[2] = z[0] * w[2] - z[1] * w[3] + z[2] * w[0] + z[3] * w[1]; + zw[3] = z[0] * w[3] + z[1] * w[2] - z[2] * w[1] + z[3] * w[0]; +} + +// xy = x cross y; +template inline +void CrossProduct(const T x[3], const T y[3], T x_cross_y[3]) { + x_cross_y[0] = x[1] * y[2] - x[2] * y[1]; + x_cross_y[1] = x[2] * y[0] - x[0] * y[2]; + x_cross_y[2] = x[0] * y[1] - x[1] * y[0]; +} + +template inline +T DotProduct(const T x[3], const T y[3]) { + return (x[0] * y[0] + x[1] * y[1] + x[2] * y[2]); +} + +template inline +void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) { + T w[3]; + T sintheta; + T costheta; + + const T theta2 = DotProduct(angle_axis, angle_axis); + if (theta2 > 0.0) { + // Away from zero, use the rodriguez formula + // + // result = pt costheta + + // (w x pt) * sintheta + + // w (w . pt) (1 - costheta) + // + // We want to be careful to only evaluate the square root if the + // norm of the angle_axis vector is greater than zero. Otherwise + // we get a division by zero. + // + const T theta = sqrt(theta2); + w[0] = angle_axis[0] / theta; + w[1] = angle_axis[1] / theta; + w[2] = angle_axis[2] / theta; + costheta = cos(theta); + sintheta = sin(theta); + T w_cross_pt[3]; + CrossProduct(w, pt, w_cross_pt); + T w_dot_pt = DotProduct(w, pt); + for (int i = 0; i < 3; ++i) { + result[i] = pt[i] * costheta + + w_cross_pt[i] * sintheta + + w[i] * (T(1.0) - costheta) * w_dot_pt; + } + } else { + // Near zero, the first order Taylor approximation of the rotation + // matrix R corresponding to a vector w and angle w is + // + // R = I + hat(w) * sin(theta) + // + // But sintheta ~ theta and theta * w = angle_axis, which gives us + // + // R = I + hat(w) + // + // and actually performing multiplication with the point pt, gives us + // R * pt = pt + w x pt. + // + // Switching to the Taylor expansion at zero helps avoid all sorts + // of numerical nastiness. + T w_cross_pt[3]; + CrossProduct(angle_axis, pt, w_cross_pt); + for (int i = 0; i < 3; ++i) { + result[i] = pt[i] + w_cross_pt[i]; + } + } +} + +} // namespace ceres + +// Clean define pollution. +#ifdef CERES_NEED_M_PI_UNDEF +#undef CERES_NEED_M_PI_UNDEF +#undef M_PI +#endif + +#endif // CERES_PUBLIC_ROTATION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h new file mode 100644 index 00000000000..968285b8f1e --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h @@ -0,0 +1,82 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A convenience class for cost functions which are statically sized. +// Compared to the dynamically-sized base class, this reduces boilerplate. + +#ifndef CERES_PUBLIC_SIZED_COST_FUNCTION_H_ +#define CERES_PUBLIC_SIZED_COST_FUNCTION_H_ + +#include +#include "ceres/cost_function.h" + +namespace ceres { + +template +class SizedCostFunction : public CostFunction { + public: + SizedCostFunction() { + // Sanity checking. + DCHECK_GT(kNumResiduals, 0) << "Cost functions must have at least " + << "one residual block."; + DCHECK_GT(N0, 0) + << "Cost functions must have at least one parameter block."; + DCHECK((!N1 && !N2 && !N3 && !N4 && !N5) || + ((N1 > 0) && !N2 && !N3 && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0))) + << "Zero block cannot precede a non-zero block. Block sizes are " + << "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", " + << N3 << ", " << N4 << ", " << N5; + + set_num_residuals(kNumResiduals); + +#define ADD_PARAMETER_BLOCK(N) \ + if (N) mutable_parameter_block_sizes()->push_back(N); + ADD_PARAMETER_BLOCK(N0); + ADD_PARAMETER_BLOCK(N1); + ADD_PARAMETER_BLOCK(N2); + ADD_PARAMETER_BLOCK(N3); + ADD_PARAMETER_BLOCK(N4); + ADD_PARAMETER_BLOCK(N5); +#undef ADD_PARAMETER_BLOCK + } + + virtual ~SizedCostFunction() { } + + // Subclasses must implement Evaluate(). +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_SIZED_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h new file mode 100644 index 00000000000..15fd7332d21 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/solver.h @@ -0,0 +1,379 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_PUBLIC_SOLVER_H_ +#define CERES_PUBLIC_SOLVER_H_ + +#include +#include +#include + +#include "ceres/iteration_callback.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/types.h" + +namespace ceres { + +class Problem; + +// Interface for non-linear least squares solvers. +class Solver { + public: + virtual ~Solver(); + + // The options structure contains, not surprisingly, options that control how + // the solver operates. The defaults should be suitable for a wide range of + // problems; however, better performance is often obtainable with tweaking. + // + // The constants are defined inside types.h + struct Options { + // Default constructor that sets up a generic sparse problem. + Options() { + minimizer_type = LEVENBERG_MARQUARDT; + max_num_iterations = 50; + max_solver_time_sec = 1.0e9; + num_threads = 1; + tau = 1e-4; + min_relative_decrease = 1e-3; + function_tolerance = 1e-6; + gradient_tolerance = 1e-10; + parameter_tolerance = 1e-8; +#ifndef CERES_NO_SUITESPARSE + linear_solver_type = SPARSE_NORMAL_CHOLESKY; +#else + linear_solver_type = DENSE_QR; +#endif // CERES_NO_SUITESPARSE + preconditioner_type = JACOBI; + num_linear_solver_threads = 1; + num_eliminate_blocks = 0; + ordering_type = NATURAL; + linear_solver_min_num_iterations = 1; + linear_solver_max_num_iterations = 500; + eta = 1e-1; + jacobi_scaling = true; + logging_type = PER_MINIMIZER_ITERATION; + minimizer_progress_to_stdout = false; + return_initial_residuals = false; + return_final_residuals = false; + lsqp_dump_format = "lm_iteration_%03d.lsqp"; + crash_and_dump_lsqp_on_failure = false; + check_gradients = false; + gradient_check_relative_precision = 1e-8; + numeric_derivative_relative_step_size = 1e-6; + update_state_every_iteration = false; + } + + // Minimizer options ---------------------------------------- + + MinimizerType minimizer_type; + + // Maximum number of iterations for the minimizer to run for. + int max_num_iterations; + + // Maximum time for which the minimizer should run for. + double max_solver_time_sec; + + // Number of threads used by Ceres for evaluating the cost and + // jacobians. + int num_threads; + + // For Levenberg-Marquardt, the initial value for the + // regularizer. This is the inversely related to the size of the + // initial trust region. + double tau; + + // For trust region methods, this is lower threshold for the + // relative decrease before a step is accepted. + double min_relative_decrease; + + // Minimizer terminates when + // + // (new_cost - old_cost) < function_tolerance * old_cost; + // + double function_tolerance; + + // Minimizer terminates when + // + // max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i| + // + // This value should typically be 1e-4 * function_tolerance. + double gradient_tolerance; + + // Minimizer terminates when + // + // |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance) + // + double parameter_tolerance; + + // Linear least squares solver options ------------------------------------- + + LinearSolverType linear_solver_type; + + // Type of preconditioner to use with the iterative linear solvers. + PreconditionerType preconditioner_type; + + // Number of threads used by Ceres to solve the Newton + // step. Currently only the SPARSE_SCHUR solver is capable of + // using this setting. + int num_linear_solver_threads; + + // For Schur reduction based methods, the first 0 to num blocks are + // eliminated using the Schur reduction. For example, when solving + // traditional structure from motion problems where the parameters are in + // two classes (cameras and points) then num_eliminate_blocks would be the + // number of points. + // + // This parameter is used in conjunction with the ordering. + // Applies to: Preprocessor and linear least squares solver. + int num_eliminate_blocks; + + // Internally Ceres reorders the parameter blocks to help the + // various linear solvers. This parameter allows the user to + // influence the re-ordering strategy used. For structure from + // motion problems use SCHUR, for other problems NATURAL (default) + // is a good choice. In case you wish to specify your own ordering + // scheme, for example in conjunction with num_eliminate_blocks, + // use USER. + OrderingType ordering_type; + + // The ordering of the parameter blocks. The solver pays attention + // to it if the ordering_type is set to USER and the vector is + // non-empty. + vector ordering; + + + // Minimum number of iterations for which the linear solver should + // run, even if the convergence criterion is satisfied. + int linear_solver_min_num_iterations; + + // Maximum number of iterations for which the linear solver should + // run. If the solver does not converge in less than + // linear_solver_max_num_iterations, then it returns + // MAX_ITERATIONS, as its termination type. + int linear_solver_max_num_iterations; + + // Forcing sequence parameter. The truncated Newton solver uses + // this number to control the relative accuracy with which the + // Newton step is computed. + // + // This constant is passed to ConjugateGradientsSolver which uses + // it to terminate the iterations when + // + // (Q_i - Q_{i-1})/Q_i < eta/i + double eta; + + // Normalize the jacobian using Jacobi scaling before calling + // the linear least squares solver. + bool jacobi_scaling; + + // Logging options --------------------------------------------------------- + + LoggingType logging_type; + + // By default the Minimizer progress is logged to VLOG(1), which + // is sent to STDERR depending on the vlog level. If this flag is + // set to true, and logging_type is not SILENT, the logging output + // is sent to STDOUT. + bool minimizer_progress_to_stdout; + + bool return_initial_residuals; + bool return_final_residuals; + + // List of iterations at which the optimizer should dump the + // linear least squares problem to disk. Useful for testing and + // benchmarking. If empty (default), no problems are dumped. + // + // This is ignored if protocol buffers are disabled. + vector lsqp_iterations_to_dump; + + // Format string for the file name used for dumping the least + // squares problem to disk. If the format is 'ascii', then the + // problem is logged to the screen; don't try this with large + // problems or expect a frozen terminal. + string lsqp_dump_format; + + // Dump the linear least squares problem to disk if the minimizer + // fails due to NUMERICAL_FAILURE and crash the process. This flag + // is useful for generating debugging information. The problem is + // dumped in a file whose name is determined by + // Solver::Options::lsqp_dump_format. + // + // Note: This requires a version of Ceres built with protocol buffers. + bool crash_and_dump_lsqp_on_failure; + + // Finite differences options ---------------------------------------------- + + // Check all jacobians computed by each residual block with finite + // differences. This is expensive since it involves computing the + // derivative by normal means (e.g. user specified, autodiff, + // etc), then also computing it using finite differences. The + // results are compared, and if they differ substantially, details + // are printed to the log. + bool check_gradients; + + // Relative precision to check for in the gradient checker. If the + // relative difference between an element in a jacobian exceeds + // this number, then the jacobian for that cost term is dumped. + double gradient_check_relative_precision; + + // Relative shift used for taking numeric derivatives. For finite + // differencing, each dimension is evaluated at slightly shifted + // values; for the case of central difference, this is what gets + // evaluated: + // + // delta = numeric_derivative_relative_step_size; + // f_initial = f(x) + // f_forward = f((1 + delta) * x) + // f_backward = f((1 - delta) * x) + // + // The finite differencing is done along each dimension. The + // reason to use a relative (rather than absolute) step size is + // that this way, numeric differentation works for functions where + // the arguments are typically large (e.g. 1e9) and when the + // values are small (e.g. 1e-5). It is possible to construct + // "torture cases" which break this finite difference heuristic, + // but they do not come up often in practice. + // + // TODO(keir): Pick a smarter number than the default above! In + // theory a good choice is sqrt(eps) * x, which for doubles means + // about 1e-8 * x. However, I have found this number too + // optimistic. This number should be exposed for users to change. + double numeric_derivative_relative_step_size; + + // If true, the user's parameter blocks are updated at the end of + // every Minimizer iteration, otherwise they are updated when the + // Minimizer terminates. This is useful if, for example, the user + // wishes to visualize the state of the optimization every + // iteration. + bool update_state_every_iteration; + + // Callbacks that are executed at the end of each iteration of the + // Minimizer. They are executed in the order that they are + // specified in this vector. By default, parameter blocks are + // updated only at the end of the optimization, i.e when the + // Minimizer terminates. This behaviour is controlled by + // update_state_every_variable. If the user wishes to have access + // to the update parameter blocks when his/her callbacks are + // executed, then set update_state_every_iteration to true. + // + // The solver does NOT take ownership of these pointers. + vector callbacks; + }; + + struct Summary { + Summary(); + + // A brief one line description of the state of the solver after + // termination. + string BriefReport() const; + + // A full multiline description of the state of the solver after + // termination. + string FullReport() const; + + // Minimizer summary ------------------------------------------------- + SolverTerminationType termination_type; + + // If the solver did not run, or there was a failure, a + // description of the error. + string error; + + // Cost of the problem before and after the optimization. See + // problem.h for definition of the cost of a problem. + double initial_cost; + double final_cost; + + // The part of the total cost that comes from residual blocks that + // were held fixed by the preprocessor because all the parameter + // blocks that they depend on were fixed. + double fixed_cost; + + // Residuals before and after the optimization. Each vector + // contains problem.NumResiduals() elements. Residuals are in the + // same order in which they were added to the problem object when + // constructing this problem. + vector initial_residuals; + vector final_residuals; + + vector iterations; + + int num_successful_steps; + int num_unsuccessful_steps; + + double preprocessor_time_in_seconds; + double minimizer_time_in_seconds; + double total_time_in_seconds; + + // Preprocessor summary. + int num_parameter_blocks; + int num_parameters; + int num_residual_blocks; + int num_residuals; + + int num_parameter_blocks_reduced; + int num_parameters_reduced; + int num_residual_blocks_reduced; + int num_residuals_reduced; + + int num_eliminate_blocks_given; + int num_eliminate_blocks_used; + + int num_threads_given; + int num_threads_used; + + int num_linear_solver_threads_given; + int num_linear_solver_threads_used; + + LinearSolverType linear_solver_type_given; + LinearSolverType linear_solver_type_used; + + PreconditionerType preconditioner_type; + OrderingType ordering_type; + }; + + // Once a least squares problem has been built, this function takes + // the problem and optimizes it based on the values of the options + // parameters. Upon return, a detailed summary of the work performed + // by the preprocessor, the non-linear minmizer and the linear + // solver are reported in the summary object. + virtual void Solve(const Options& options, + Problem* problem, + Solver::Summary* summary); +}; + +// Helper function which avoids going through the interface. +void Solve(const Solver::Options& options, + Problem* problem, + Solver::Summary* summary); + +} // namespace ceres + +#endif // CERES_PUBLIC_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/types.h b/extern/libmv/third_party/ceres/include/ceres/types.h new file mode 100644 index 00000000000..b83a266d1ba --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/types.h @@ -0,0 +1,224 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Enums and other top level class definitions. +// +// Note: internal/types.cc defines stringification routines for some +// of these enums. Please update those routines if you extend or +// remove enums from here. + +#ifndef CERES_PUBLIC_TYPES_H_ +#define CERES_PUBLIC_TYPES_H_ + +namespace ceres { + +// Basic integer types. These typedefs are in the Ceres namespace to avoid +// conflicts with other packages having similar typedefs. +typedef short int16; +typedef int int32; + +// Argument type used in interfaces that can optionally take ownership +// of a passed in argument. If TAKE_OWNERSHIP is passed, the called +// object takes ownership of the pointer argument, and will call +// delete on it upon completion. +enum Ownership { + DO_NOT_TAKE_OWNERSHIP, + TAKE_OWNERSHIP +}; + +// TODO(keir): Considerably expand the explanations of each solver type. +enum LinearSolverType { + // These solvers are for general rectangular systems formed from the + // normal equations A'A x = A'b. They are direct solvers and do not + // assume any special problem structure. + + // Solve the normal equations using a sparse cholesky solver; based + // on CHOLMOD. + SPARSE_NORMAL_CHOLESKY, + + // Solve the normal equations using a dense QR solver; based on + // Eigen. + DENSE_QR, + + // Specialized solvers, specific to problems with a generalized + // bi-partitite structure. + + // Solves the reduced linear system using a dense Cholesky solver; + // based on Eigen. + DENSE_SCHUR, + + // Solves the reduced linear system using a sparse Cholesky solver; + // based on CHOLMOD. + SPARSE_SCHUR, + + // Solves the reduced linear system using Conjugate Gradients, based + // on a new Ceres implementation. Suitable for large scale + // problems. + ITERATIVE_SCHUR, + + // Conjugate gradients on the normal equations. + CGNR +}; + +enum PreconditionerType { + // Trivial preconditioner - the identity matrix. + IDENTITY, + + // Block diagonal of the Gauss-Newton Hessian. + JACOBI, + + // Block diagonal of the Schur complement. This preconditioner may + // only be used with the ITERATIVE_SCHUR solver. Requires + // SuiteSparse/CHOLMOD. + SCHUR_JACOBI, + + // Visibility clustering based preconditioners. + // + // These preconditioners are well suited for Structure from Motion + // problems, particularly problems arising from community photo + // collections. These preconditioners use the visibility structure + // of the scene to determine the sparsity structure of the + // preconditioner. Requires SuiteSparse/CHOLMOD. + CLUSTER_JACOBI, + CLUSTER_TRIDIAGONAL +}; + +enum LinearSolverTerminationType { + // Termination criterion was met. For factorization based solvers + // the tolerance is assumed to be zero. Any user provided values are + // ignored. + TOLERANCE, + + // Solver ran for max_num_iterations and terminated before the + // termination tolerance could be satified. + MAX_ITERATIONS, + + // Solver is stuck and further iterations will not result in any + // measurable progress. + STAGNATION, + + // Solver failed. Solver was terminated due to numerical errors. The + // exact cause of failure depends on the particular solver being + // used. + FAILURE +}; + +enum OrderingType { + // The order in which the parameter blocks were defined. + NATURAL, + + // Use the ordering specificed in the vector ordering. + USER, + + // Automatically figure out the best ordering to use the schur + // complement based solver. + SCHUR +}; + +// Logging options +// The options get progressively noisier. +enum LoggingType { + SILENT, + PER_MINIMIZER_ITERATION +}; + +enum MinimizerType { + LEVENBERG_MARQUARDT +}; + +enum SolverTerminationType { + // The minimizer did not run at all; usually due to errors in the user's + // Problem or the solver options. + DID_NOT_RUN, + + // The solver ran for maximum number of iterations specified by the + // user, but none of the convergence criterion specified by the user + // were met. + NO_CONVERGENCE, + + // Minimizer terminated because + // (new_cost - old_cost) < function_tolerance * old_cost; + FUNCTION_TOLERANCE, + + // Minimizer terminated because + // max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i| + GRADIENT_TOLERANCE, + + // Minimized terminated because + // |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance) + PARAMETER_TOLERANCE, + + // The minimizer terminated because it encountered a numerical error + // that it could not recover from. + NUMERICAL_FAILURE, + + // Using an IterationCallback object, user code can control the + // minimizer. The following enums indicate that the user code was + // responsible for termination. + + // User's IterationCallback returned SOLVER_ABORT. + USER_ABORT, + + // User's IterationCallback returned SOLVER_TERMINATE_SUCCESSFULLY + USER_SUCCESS +}; + +// Enums used by the IterationCallback instances to indicate to the +// solver whether it should continue solving, the user detected an +// error or the solution is good enough and the solver should +// terminate. +enum CallbackReturnType { + // Continue solving to next iteration. + SOLVER_CONTINUE, + + // Terminate solver, and do not update the parameter blocks upon + // return. Unless the user has set + // Solver:Options:::update_state_every_iteration, in which case the + // state would have been updated every iteration + // anyways. Solver::Summary::termination_type is set to USER_ABORT. + SOLVER_ABORT, + + // Terminate solver, update state and + // return. Solver::Summary::termination_type is set to USER_SUCCESS. + SOLVER_TERMINATE_SUCCESSFULLY +}; + +const char* LinearSolverTypeToString(LinearSolverType type); +const char* PreconditionerTypeToString(PreconditionerType type); +const char* LinearSolverTerminationTypeToString( + LinearSolverTerminationType type); +const char* OrderingTypeToString(OrderingType type); +const char* SolverTerminationTypeToString(SolverTerminationType type); + +bool IsSchurType(LinearSolverType type); + +} // namespace ceres + +#endif // CERES_PUBLIC_TYPES_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc new file mode 100644 index 00000000000..05e63eb560b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc @@ -0,0 +1,73 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/block_evaluate_preparer.h" + +#include +#include "ceres/block_sparse_matrix.h" +#include "ceres/casts.h" +#include "ceres/parameter_block.h" +#include "ceres/residual_block.h" +#include "ceres/sparse_matrix.h" + +namespace ceres { +namespace internal { + +void BlockEvaluatePreparer::Init(int** jacobian_layout) { + jacobian_layout_ = jacobian_layout; +} + +// Point the jacobian blocks directly into the block sparse matrix. +void BlockEvaluatePreparer::Prepare(const ResidualBlock* residual_block, + int residual_block_index, + SparseMatrix* jacobian, + double** jacobians) const { + CHECK(jacobian != NULL); + double* jacobian_values = + down_cast(jacobian)->mutable_values(); + + const int* jacobian_block_offset = jacobian_layout_[residual_block_index]; + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + for (int j = 0; j < num_parameter_blocks; ++j) { + if (!residual_block->parameter_blocks()[j]->IsConstant()) { + jacobians[j] = jacobian_values + *jacobian_block_offset; + + // The jacobian_block_offset can't be indexed with 'j' since the code + // that creates the layout strips out any blocks for inactive + // parameters. Instead, bump the pointer for active parameters only. + jacobian_block_offset++; + } else { + jacobians[j] = NULL; + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h new file mode 100644 index 00000000000..a7869311e6e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h @@ -0,0 +1,67 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A evaluate preparer which puts jacobian the evaluated jacobian blocks +// directly into their final resting place in an overall block sparse matrix. +// The evaluator takes care to avoid evaluating the jacobian for fixed +// parameters. + +#ifndef CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ +#define CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ + +namespace ceres { +namespace internal { + +class ResidualBlock; +class SparseMatrix; + +class BlockEvaluatePreparer { + public: + // Using Init() instead of a constructor allows for allocating this structure + // with new[]. This is because C++ doesn't allow passing arguments to objects + // constructed with new[] (as opposed to plain 'new'). + void Init(int** jacobian_layout); + + // EvaluatePreparer interface + + // Point the jacobian blocks directly into the block sparse matrix. + void Prepare(const ResidualBlock* residual_block, + int residual_block_index, + SparseMatrix* jacobian, + double** jacobians) const; + + private: + int const* const* jacobian_layout_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc new file mode 100644 index 00000000000..1a5001f9c71 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc @@ -0,0 +1,136 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/block_jacobi_preconditioner.h" + +#include "Eigen/Cholesky" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/casts.h" +#include "ceres/integral_types.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +BlockJacobiPreconditioner::BlockJacobiPreconditioner( + const LinearOperator& A) + : block_structure_( + *(down_cast(&A)->block_structure())), + num_rows_(A.num_rows()) { + // Calculate the amount of storage needed. + int storage_needed = 0; + for (int c = 0; c < block_structure_.cols.size(); ++c) { + int size = block_structure_.cols[c].size; + storage_needed += size * size; + } + + // Size the offsets and storage. + blocks_.resize(block_structure_.cols.size()); + block_storage_.resize(storage_needed); + + // Put pointers to the storage in the offsets. + double* block_cursor = &block_storage_[0]; + for (int c = 0; c < block_structure_.cols.size(); ++c) { + int size = block_structure_.cols[c].size; + blocks_[c] = block_cursor; + block_cursor += size * size; + } +} + +BlockJacobiPreconditioner::~BlockJacobiPreconditioner() { +} + +void BlockJacobiPreconditioner::Update(const LinearOperator& matrix, const double* D) { + const BlockSparseMatrix& A = *(down_cast(&matrix)); + const CompressedRowBlockStructure* bs = A.block_structure(); + + // Compute the diagonal blocks by block inner products. + std::fill(block_storage_.begin(), block_storage_.end(), 0.0); + for (int r = 0; r < bs->rows.size(); ++r) { + const int row_block_size = bs->rows[r].block.size; + const vector& cells = bs->rows[r].cells; + const double* row_values = A.RowBlockValues(r); + for (int c = 0; c < cells.size(); ++c) { + const int col_block_size = bs->cols[cells[c].block_id].size; + ConstMatrixRef m(row_values + cells[c].position, + row_block_size, + col_block_size); + + MatrixRef(blocks_[cells[c].block_id], + col_block_size, + col_block_size).noalias() += m.transpose() * m; + + // TODO(keir): Figure out when the below expression is actually faster + // than doing the full rank update. The issue is that for smaller sizes, + // the rankUpdate() function is slower than the full product done above. + // + // On the typical bundling problems, the above product is ~5% faster. + // + // MatrixRef(blocks_[cells[c].block_id], + // col_block_size, + // col_block_size).selfadjointView().rankUpdate(m); + // + } + } + + // Add the diagonal and invert each block. + for (int c = 0; c < bs->cols.size(); ++c) { + const int size = block_structure_.cols[c].size; + const int position = block_structure_.cols[c].position; + MatrixRef block(blocks_[c], size, size); + + if (D != NULL) { + block.diagonal() += ConstVectorRef(D + position, size).array().square().matrix(); + } + + block = block.selfadjointView() + .ldlt() + .solve(Matrix::Identity(size, size)); + } +} + +void BlockJacobiPreconditioner::RightMultiply(const double* x, double* y) const { + for (int c = 0; c < block_structure_.cols.size(); ++c) { + const int size = block_structure_.cols[c].size; + const int position = block_structure_.cols[c].position; + ConstMatrixRef D(blocks_[c], size, size); + ConstVectorRef x_block(x + position, size); + VectorRef y_block(y + position, size); + y_block += D * x_block; + } +} + +void BlockJacobiPreconditioner::LeftMultiply(const double* x, double* y) const { + RightMultiply(x, y); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h new file mode 100644 index 00000000000..91cfeddb688 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h @@ -0,0 +1,84 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_ +#define CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_ + +#include +#include "ceres/linear_operator.h" + +namespace ceres { +namespace internal { + +class CompressedRowBlockStructure; +class LinearOperator; +class SparseMatrix; + +// A block Jacobi preconditioner. This is intended for use with conjugate +// gradients, or other iterative symmetric solvers. To use the preconditioner, +// create one by passing a BlockSparseMatrix as the linear operator "A" to the +// constructor. This fixes the sparsity pattern to the pattern of the matrix +// A^TA. +// +// Before each use of the preconditioner in a solve with conjugate gradients, +// update the matrix by running Update(A, D). The values of the matrix A are +// inspected to construct the preconditioner. The vector D is applied as the +// D^TD diagonal term. +class BlockJacobiPreconditioner : public LinearOperator { + public: + // A must remain valid while the BlockJacobiPreconditioner is. + BlockJacobiPreconditioner(const LinearOperator& A); + virtual ~BlockJacobiPreconditioner(); + + // Update the preconditioner with the values found in A. The sparsity pattern + // must match that of the A passed to the constructor. D is a vector that + // must have the same number of rows as A, and is applied as a diagonal in + // addition to the block diagonals of A. + void Update(const LinearOperator& A, const double* D); + + // LinearOperator interface. + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_rows_; } + + private: + std::vector blocks_; + std::vector block_storage_; + int num_rows_; + + // The block structure of the matrix this preconditioner is for (e.g. J). + const CompressedRowBlockStructure& block_structure_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc new file mode 100644 index 00000000000..52a58bb43a6 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc @@ -0,0 +1,209 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/block_jacobian_writer.h" + +#include "ceres/block_evaluate_preparer.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { +namespace { + +// Given the residual block ordering, build a lookup table to determine which +// per-parameter jacobian goes where in the overall program jacobian. +// +// Since we expect to use a Schur type linear solver to solve the LM step, take +// extra care to place the E blocks and the F blocks contiguously. E blocks are +// the first num_eliminate_blocks parameter blocks as indicated by the parameter +// block ordering. The remaining parameter blocks are the F blocks. +// +// TODO(keir): Consider if we should use a boolean for each parameter block +// instead of num_eliminate_blocks. +void BuildJacobianLayout(const Program& program, + int num_eliminate_blocks, + vector* jacobian_layout, + vector* jacobian_layout_storage) { + const vector& residual_blocks = program.residual_blocks(); + + // Iterate over all the active residual blocks and determine how many E blocks + // are there. This will determine where the F blocks start in the jacobian + // matrix. Also compute the number of jacobian blocks. + int f_block_pos = 0; + int num_jacobian_blocks = 0; + for (int i = 0; i < residual_blocks.size(); ++i) { + ResidualBlock* residual_block = residual_blocks[i]; + const int num_residuals = residual_block->NumResiduals(); + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + + // Advance f_block_pos over each E block for this residual. + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + // Only count blocks for active parameters. + num_jacobian_blocks++; + if (parameter_block->index() < num_eliminate_blocks) { + f_block_pos += num_residuals * parameter_block->LocalSize(); + } + } + } + } + + // We now know that the E blocks are laid out starting at zero, and the F + // blocks are laid out starting at f_block_pos. Iterate over the residual + // blocks again, and this time fill the jacobian_layout array with the + // position information. + + jacobian_layout->resize(program.NumResidualBlocks()); + jacobian_layout_storage->resize(num_jacobian_blocks); + + int e_block_pos = 0; + int* jacobian_pos = &(*jacobian_layout_storage)[0]; + for (int i = 0; i < residual_blocks.size(); ++i) { + const ResidualBlock* residual_block = residual_blocks[i]; + const int num_residuals = residual_block->NumResiduals(); + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + + (*jacobian_layout)[i] = jacobian_pos; + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + const int parameter_block_index = parameter_block->index(); + if (parameter_block->IsConstant()) { + continue; + } + const int jacobian_block_size = + num_residuals * parameter_block->LocalSize(); + if (parameter_block_index < num_eliminate_blocks) { + *jacobian_pos = e_block_pos; + e_block_pos += jacobian_block_size; + } else { + *jacobian_pos = f_block_pos; + f_block_pos += jacobian_block_size; + } + jacobian_pos++; + } + } +} + +} // namespace + +BlockJacobianWriter::BlockJacobianWriter(const Evaluator::Options& options, + Program* program) + : program_(program) { + CHECK_GE(options.num_eliminate_blocks, 0) + << "num_eliminate_blocks must be greater than 0."; + + BuildJacobianLayout(*program, + options.num_eliminate_blocks, + &jacobian_layout_, + &jacobian_layout_storage_); +} + +// Create evaluate prepareres that point directly into the final jacobian. This +// makes the final Write() a nop. +BlockEvaluatePreparer* BlockJacobianWriter::CreateEvaluatePreparers( + int num_threads) { + BlockEvaluatePreparer* preparers = new BlockEvaluatePreparer[num_threads]; + for (int i = 0; i < num_threads; i++) { + preparers[i].Init(&jacobian_layout_[0]); + } + return preparers; +} + +SparseMatrix* BlockJacobianWriter::CreateJacobian() const { + CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; + + const vector& parameter_blocks = + program_->parameter_blocks(); + + // Construct the column blocks. + bs->cols.resize(parameter_blocks.size()); + for (int i = 0, cursor = 0; i < parameter_blocks.size(); ++i) { + CHECK_NE(parameter_blocks[i]->index(), -1); + CHECK(!parameter_blocks[i]->IsConstant()); + bs->cols[i].size = parameter_blocks[i]->LocalSize(); + bs->cols[i].position = cursor; + cursor += bs->cols[i].size; + } + + // Construct the cells in each row. + const vector& residual_blocks = + program_->residual_blocks(); + int row_block_position = 0; + bs->rows.resize(residual_blocks.size()); + for (int i = 0; i < residual_blocks.size(); ++i) { + const ResidualBlock* residual_block = residual_blocks[i]; + CompressedRow* row = &bs->rows[i]; + + row->block.size = residual_block->NumResiduals(); + row->block.position = row_block_position; + row_block_position += row->block.size; + + // Size the row by the number of active parameters in this residual. + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + int num_active_parameter_blocks = 0; + for (int j = 0; j < num_parameter_blocks; ++j) { + if (residual_block->parameter_blocks()[j]->index() != -1) { + num_active_parameter_blocks++; + } + } + row->cells.resize(num_active_parameter_blocks); + + // Add layout information for the active parameters in this row. + for (int j = 0, k = 0; j < num_parameter_blocks; ++j) { + const ParameterBlock* parameter_block = + residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + Cell& cell = row->cells[k]; + cell.block_id = parameter_block->index(); + cell.position = jacobian_layout_[i][k]; + + // Only increment k for active parameters, since there is only layout + // information for active parameters. + k++; + } + } + + sort(row->cells.begin(), row->cells.end(), CellLessThan); + } + + BlockSparseMatrix* jacobian = new BlockSparseMatrix(bs); + CHECK_NOTNULL(jacobian); + return jacobian; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.h b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.h new file mode 100644 index 00000000000..140c7211129 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.h @@ -0,0 +1,127 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A jacobian writer that writes to block sparse matrices. The "writer" name is +// misleading, since the Write() operation on the block jacobian writer does not +// write anything. Instead, the Prepare() method on the BlockEvaluatePreparers +// makes a jacobians array which has direct pointers into the block sparse +// jacobian. When the cost function is evaluated, the jacobian blocks get placed +// directly in their final location. + +#ifndef CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ +#define CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ + +#include +#include "ceres/evaluator.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +class BlockEvaluatePreparer; +class Program; +class SparseMatrix; + +class BlockJacobianWriter { + public: + BlockJacobianWriter(const Evaluator::Options& options, + Program* program); + + // JacobianWriter interface. + + // Create evaluate prepareres that point directly into the final jacobian. + // This makes the final Write() a nop. + BlockEvaluatePreparer* CreateEvaluatePreparers(int num_threads); + + SparseMatrix* CreateJacobian() const; + + void Write(int /* residual_id */, + int /* residual_offset */, + double** /* jacobians */, + SparseMatrix* /* jacobian */) { + // This is a noop since the blocks were written directly into their final + // position by the outside evaluate call, thanks to the jacobians array + // prepared by the BlockEvaluatePreparers. + } + + private: + Program* program_; + + // Stores the position of each residual / parameter jacobian. + // + // The block sparse matrix that this writer writes to is stored as a set of + // contiguos dense blocks, one after each other; see BlockSparseMatrix. The + // "double* values_" member of the block sparse matrix contains all of these + // blocks. Given a pointer to the first element of a block and the size of + // that block, it's possible to write to it. + // + // In the case of a block sparse jacobian, the jacobian writer needs a way to + // find the offset in the values_ array of each residual/parameter jacobian + // block. + // + // That is the purpose of jacobian_layout_. + // + // In particular, jacobian_layout_[i][j] is the offset in the values_ array of + // the derivative of residual block i with respect to the parameter block at + // active argument position j. + // + // The active qualifier means that non-active parameters do not count. Care + // must be taken when indexing into jacobian_layout_ to account for this. + // Consider a single residual example: + // + // r(x, y, z) + // + // with r in R^3, x in R^4, y in R^2, and z in R^5. + // Take y as a constant (non-active) parameter. + // Take r as residual number 0. + // + // In this case, the active arguments are only (x, z), so the active argument + // position for x is 0, and the active argument position for z is 1. This is + // similar to thinking of r as taking only 2 parameters: + // + // r(x, z) + // + // There are only 2 jacobian blocks: dr/dx and dr/dz. jacobian_layout_ would + // have the following contents: + // + // jacobian_layout_[0] = { 0, 12 } + // + // which indicates that dr/dx is located at values_[0], and dr/dz is at + // values_[12]. See BlockEvaluatePreparer::Prepare()'s comments about 'j'. + vector jacobian_layout_; + + // The pointers in jacobian_layout_ point directly into this vector. + vector jacobian_layout_storage_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc new file mode 100644 index 00000000000..2afaf5e2ea2 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc @@ -0,0 +1,83 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_random_access_dense_matrix.h" + +#include +#include +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +BlockRandomAccessDenseMatrix::BlockRandomAccessDenseMatrix( + const vector& blocks) { + block_layout_.resize(blocks.size(), 0); + num_rows_ = 0; + for (int i = 0; i < blocks.size(); ++i) { + block_layout_[i] = num_rows_; + num_rows_ += blocks[i]; + } + + values_.reset(new double[num_rows_ * num_rows_]); + CHECK_NOTNULL(values_.get()); + cell_info_.values = values_.get(); + SetZero(); +} + +// Assume that the user does not hold any locks on any cell blocks +// when they are calling SetZero. +BlockRandomAccessDenseMatrix::~BlockRandomAccessDenseMatrix() { +} + +CellInfo* BlockRandomAccessDenseMatrix::GetCell(const int row_block_id, + const int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride) { + *row = block_layout_[row_block_id]; + *col = block_layout_[col_block_id]; + *row_stride = num_rows_; + *col_stride = num_rows_; + return &cell_info_; +} + +// Assume that the user does not hold any locks on any cell blocks +// when they are calling SetZero. +void BlockRandomAccessDenseMatrix::SetZero() { + if (num_rows_) { + VectorRef(values_.get(), num_rows_ * num_rows_).setZero(); + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h new file mode 100644 index 00000000000..3a0096209f7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h @@ -0,0 +1,98 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_ +#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_ + +#include "ceres/block_random_access_matrix.h" + +#include + +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +// A square block random accessible matrix with the same row and +// column block structure. All cells are stored in the same single +// array, so that its also accessible as a dense matrix of size +// num_rows x num_cols. +// +// This class is NOT thread safe. Since all n^2 cells are stored, +// GetCell never returns NULL for any (row_block_id, col_block_id) +// pair. +// +// ReturnCell is a nop. +class BlockRandomAccessDenseMatrix : public BlockRandomAccessMatrix { + public: + // blocks is a vector of block sizes. The resulting matrix has + // blocks.size() * blocks.size() cells. + explicit BlockRandomAccessDenseMatrix(const vector& blocks); + + // The destructor is not thread safe. It assumes that no one is + // modifying any cells when the matrix is being destroyed. + virtual ~BlockRandomAccessDenseMatrix(); + + // BlockRandomAccessMatrix interface. + virtual CellInfo* GetCell(int row_block_id, + int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride); + + // This is not a thread safe method, it assumes that no cell is + // locked. + virtual void SetZero(); + + // Since the matrix is square with the same row and column block + // structure, num_rows() = num_cols(). + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_rows_; } + + // The underlying matrix storing the cells. + const double* values() const { return values_.get(); } + double* mutable_values() { return values_.get(); } + + private: + CellInfo cell_info_; + int num_rows_; + vector block_layout_; + scoped_array values_; + + DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessDenseMatrix); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.cc new file mode 100644 index 00000000000..58fe4a10de3 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.cc @@ -0,0 +1,40 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_random_access_matrix.h" + +namespace ceres { +namespace internal { + +BlockRandomAccessMatrix::~BlockRandomAccessMatrix() { +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h new file mode 100644 index 00000000000..f398af3be87 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h @@ -0,0 +1,132 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Interface for matrices that allow block based random access. + +#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_MATRIX_H_ +#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_MATRIX_H_ + +#include "ceres/mutex.h" + +namespace ceres { +namespace internal { + +// A matrix implementing the BlockRandomAccessMatrix interface is a +// matrix whose rows and columns are divided into blocks. For example +// the matrix A: +// +// 3 4 5 +// A = 5 [c_11 c_12 c_13] +// 4 [c_21 c_22 c_23] +// +// has row blocks of size 5 and 4, and column blocks of size 3, 4 and +// 5. It has six cells corresponding to the six row-column block +// combinations. +// +// BlockRandomAccessMatrix objects provide access to cells c_ij using +// the GetCell method. when a cell is present, GetCell will return a +// CellInfo object containing a pointer to an array which contains the +// cell as a submatrix and a mutex that guards this submatrix. If the +// user is accessing the matrix concurrently, it is his responsibility +// to use the mutex to exclude other writers from writing to the cell +// concurrently. +// +// There is no requirement that all cells be present, i.e. the matrix +// itself can be block sparse. When a cell is not present, the GetCell +// method will return a NULL pointer. +// +// There is no requirement about how the cells are stored beyond that +// form a dense submatrix of a larger dense matrix. Like everywhere +// else in Ceres, RowMajor storage assumed. +// +// Example usage: +// +// BlockRandomAccessMatrix* A = new BlockRandomAccessMatrixSubClass(...) +// +// int row, col, row_stride, col_stride; +// CellInfo* cell = A->GetCell(row_block_id, col_block_id, +// &row, &col, +// &row_stride, &col_stride); +// +// if (cell != NULL) { +// MatrixRef m(cell->values, row_stride, col_stride); +// MutexLock l(&cell->m); +// m.block(row, col, row_block_size, col_block_size) = ... +// } + +// Structure to carry a pointer to the array containing a cell and the +// Mutex guarding it. +struct CellInfo { + CellInfo() + : values(NULL) { + } + + explicit CellInfo(double* ptr) + : values(ptr) { + } + + double* values; + Mutex m; +}; + +class BlockRandomAccessMatrix { + public: + virtual ~BlockRandomAccessMatrix(); + + // If the cell (row_block_id, col_block_id) is present, then return + // a CellInfo with a pointer to the dense matrix containing it, + // otherwise return NULL. The dense matrix containing this cell has + // size row_stride, col_stride and the cell is located at position + // (row, col) within this matrix. + // + // The size of the cell is row_block_size x col_block_size is + // assumed known to the caller. row_block_size less than or equal to + // row_stride and col_block_size is upper bounded by col_stride. + virtual CellInfo* GetCell(int row_block_id, + int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride) = 0; + + // Zero out the values of the array. The structure of the matrix + // (size and sparsity) is preserved. + virtual void SetZero() = 0; + + // Number of scalar rows and columns in the matrix, i.e the sum of + // all row blocks and column block sizes respectively. + virtual int num_rows() const = 0; + virtual int num_cols() const = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc new file mode 100644 index 00000000000..c496fcd13de --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc @@ -0,0 +1,158 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_random_access_sparse_matrix.h" + +#include +#include +#include +#include +#include +#include "ceres/mutex.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( + const vector& blocks, + const set >& block_pairs) + : kMaxRowBlocks(10 * 1000 * 1000), + blocks_(blocks) { + CHECK_LT(blocks.size(), kMaxRowBlocks); + + // Build the row/column layout vector and count the number of scalar + // rows/columns. + int num_cols = 0; + vector col_layout; + for (int i = 0; i < blocks_.size(); ++i) { + col_layout.push_back(num_cols); + num_cols += blocks_[i]; + } + + // Count the number of scalar non-zero entries and build the layout + // object for looking into the values array of the + // TripletSparseMatrix. + int num_nonzeros = 0; + for (set >::const_iterator it = block_pairs.begin(); + it != block_pairs.end(); + ++it) { + const int row_block_size = blocks_[it->first]; + const int col_block_size = blocks_[it->second]; + num_nonzeros += row_block_size * col_block_size; + } + + VLOG(1) << "Matrix Size [" << num_cols + << "," << num_cols + << "] " << num_nonzeros; + + tsm_.reset(new TripletSparseMatrix(num_cols, num_cols, num_nonzeros)); + tsm_->set_num_nonzeros(num_nonzeros); + int* rows = tsm_->mutable_rows(); + int* cols = tsm_->mutable_cols(); + double* values = tsm_->mutable_values(); + + int pos = 0; + for (set >::const_iterator it = block_pairs.begin(); + it != block_pairs.end(); + ++it) { + const int row_block_size = blocks_[it->first]; + const int col_block_size = blocks_[it->second]; + layout_[IntPairToLong(it->first, it->second)] = + new CellInfo(values + pos); + pos += row_block_size * col_block_size; + } + + // Fill the sparsity pattern of the underlying matrix. + for (set >::const_iterator it = block_pairs.begin(); + it != block_pairs.end(); + ++it) { + const int row_block_id = it->first; + const int col_block_id = it->second; + const int row_block_size = blocks_[row_block_id]; + const int col_block_size = blocks_[col_block_id]; + int pos = + layout_[IntPairToLong(row_block_id, col_block_id)]->values - values; + for (int r = 0; r < row_block_size; ++r) { + for (int c = 0; c < col_block_size; ++c, ++pos) { + rows[pos] = col_layout[row_block_id] + r; + cols[pos] = col_layout[col_block_id] + c; + values[pos] = 1.0; + DCHECK_LT(rows[pos], tsm_->num_rows()); + DCHECK_LT(cols[pos], tsm_->num_rows()); + } + } + } +} + +// Assume that the user does not hold any locks on any cell blocks +// when they are calling SetZero. +BlockRandomAccessSparseMatrix::~BlockRandomAccessSparseMatrix() { + for (LayoutType::iterator it = layout_.begin(); + it != layout_.end(); + ++it) { + delete it->second; + } +} + +CellInfo* BlockRandomAccessSparseMatrix::GetCell(int row_block_id, + int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride) { + const LayoutType::iterator it = + layout_.find(IntPairToLong(row_block_id, col_block_id)); + if (it == layout_.end()) { + return NULL; + } + + // Each cell is stored contiguously as its own little dense matrix. + *row = 0; + *col = 0; + *row_stride = blocks_[row_block_id]; + *col_stride = blocks_[col_block_id]; + return it->second; +} + +// Assume that the user does not hold any locks on any cell blocks +// when they are calling SetZero. +void BlockRandomAccessSparseMatrix::SetZero() { + if (tsm_->num_nonzeros()) { + VectorRef(tsm_->mutable_values(), + tsm_->num_nonzeros()).setZero(); + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h new file mode 100644 index 00000000000..12613c3daa0 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h @@ -0,0 +1,109 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_ + +#include +#include +#include +#include "ceres/mutex.h" +#include "ceres/block_random_access_matrix.h" +#include "ceres/collections_port.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +// A threaf safe square block sparse implementation of +// BlockRandomAccessMatrix. Internally a TripletSparseMatrix is used +// for doing the actual storage. This class augments this matrix with +// an unordered_map that allows random read/write access. +class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix { + public: + // blocks is an array of block sizes. block_pairs is a set of + // pairs to identify the non-zero cells + // of this matrix. + BlockRandomAccessSparseMatrix(const vector& blocks, + const set >& block_pairs); + + // The destructor is not thread safe. It assumes that no one is + // modifying any cells when the matrix is being destroyed. + virtual ~BlockRandomAccessSparseMatrix(); + + // BlockRandomAccessMatrix Interface. + virtual CellInfo* GetCell(int row_block_id, + int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride); + + // This is not a thread safe method, it assumes that no cell is + // locked. + virtual void SetZero(); + virtual bool IsThreadSafe() const { return true; } + + // Since the matrix is square, num_rows() == num_cols(). + virtual int num_rows() const { return tsm_->num_rows(); } + virtual int num_cols() const { return tsm_->num_cols(); } + + // Access to the underlying matrix object. + const TripletSparseMatrix* matrix() const { return tsm_.get(); } + TripletSparseMatrix* mutable_matrix() { return tsm_.get(); } + + private: + long int IntPairToLong(int a, int b) { + return a * kMaxRowBlocks + b; + } + + const int kMaxRowBlocks; + // row/column block sizes. + const vector blocks_; + + // A mapping from to the position in + // the values array of tsm_ where the block is stored. + typedef HashMap LayoutType; + LayoutType layout_; + + // The underlying matrix object which actually stores the cells. + scoped_ptr tsm_; + + DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessSparseMatrix); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc new file mode 100644 index 00000000000..c1be9402b78 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc @@ -0,0 +1,263 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_sparse_matrix.h" + +#include +#include +#include +#include +#include "ceres/block_structure.h" +#include "ceres/matrix_proto.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +BlockSparseMatrix::~BlockSparseMatrix() {} + +BlockSparseMatrix::BlockSparseMatrix( + CompressedRowBlockStructure* block_structure) + : num_rows_(0), + num_cols_(0), + num_nonzeros_(0), + values_(NULL), + block_structure_(block_structure) { + CHECK_NOTNULL(block_structure_.get()); + + // Count the number of columns in the matrix. + for (int i = 0; i < block_structure_->cols.size(); ++i) { + num_cols_ += block_structure_->cols[i].size; + } + + // Count the number of non-zero entries and the number of rows in + // the matrix. + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_size = block_structure_->rows[i].block.size; + num_rows_ += row_block_size; + + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + num_nonzeros_ += col_block_size * row_block_size; + } + } + + CHECK_GE(num_rows_, 0); + CHECK_GE(num_cols_, 0); + CHECK_GE(num_nonzeros_, 0); + VLOG(2) << "Allocating values array with " + << num_nonzeros_ * sizeof(double) << " bytes."; // NOLINT + values_.reset(new double[num_nonzeros_]); + CHECK_NOTNULL(values_.get()); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +BlockSparseMatrix::BlockSparseMatrix(const SparseMatrixProto& outer_proto) { + CHECK(outer_proto.has_block_matrix()); + + const BlockSparseMatrixProto& proto = outer_proto.block_matrix(); + CHECK(proto.has_num_rows()); + CHECK(proto.has_num_cols()); + CHECK_EQ(proto.num_nonzeros(), proto.values_size()); + + num_rows_ = proto.num_rows(); + num_cols_ = proto.num_cols(); + num_nonzeros_ = proto.num_nonzeros(); + + // Copy out the values into *this. + values_.reset(new double[num_nonzeros_]); + for (int i = 0; i < proto.num_nonzeros(); ++i) { + values_[i] = proto.values(i); + } + + // Create the block structure according to the proto. + block_structure_.reset(new CompressedRowBlockStructure); + ProtoToBlockStructure(proto.block_structure(), block_structure_.get()); +} +#endif + +void BlockSparseMatrix::SetZero() { + fill(values_.get(), values_.get() + num_nonzeros_, 0.0); +} + +void BlockSparseMatrix::RightMultiply(const double* x, double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_pos = block_structure_->rows[i].block.position; + int row_block_size = block_structure_->rows[i].block.size; + VectorRef yref(y + row_block_pos, row_block_size); + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + ConstVectorRef xref(x + col_block_pos, col_block_size); + MatrixRef m(values_.get() + cells[j].position, + row_block_size, col_block_size); + yref += m.lazyProduct(xref); + } + } +} + +void BlockSparseMatrix::LeftMultiply(const double* x, double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_pos = block_structure_->rows[i].block.position; + int row_block_size = block_structure_->rows[i].block.size; + const ConstVectorRef xref(x + row_block_pos, row_block_size); + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + VectorRef yref(y + col_block_pos, col_block_size); + MatrixRef m(values_.get() + cells[j].position, + row_block_size, col_block_size); + yref += m.transpose().lazyProduct(xref); + } + } +} + +void BlockSparseMatrix::SquaredColumnNorm(double* x) const { + CHECK_NOTNULL(x); + VectorRef(x, num_cols_).setZero(); + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + const MatrixRef m(values_.get() + cells[j].position, + row_block_size, col_block_size); + VectorRef(x + col_block_pos, col_block_size) += m.colwise().squaredNorm(); + } + } +} + +void BlockSparseMatrix::ScaleColumns(const double* scale) { + CHECK_NOTNULL(scale); + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + MatrixRef m(values_.get() + cells[j].position, + row_block_size, col_block_size); + m *= ConstVectorRef(scale + col_block_pos, col_block_size).asDiagonal(); + } + } +} + +void BlockSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { + CHECK_NOTNULL(dense_matrix); + + dense_matrix->resize(num_rows_, num_cols_); + dense_matrix->setZero(); + Matrix& m = *dense_matrix; + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_pos = block_structure_->rows[i].block.position; + int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + int jac_pos = cells[j].position; + m.block(row_block_pos, col_block_pos, row_block_size, col_block_size) + += MatrixRef(values_.get() + jac_pos, row_block_size, col_block_size); + } + } +} + +void BlockSparseMatrix::ToTripletSparseMatrix( + TripletSparseMatrix* matrix) const { + CHECK_NOTNULL(matrix); + + matrix->Reserve(num_nonzeros_); + matrix->Resize(num_rows_, num_cols_); + matrix->SetZero(); + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_pos = block_structure_->rows[i].block.position; + int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + int jac_pos = cells[j].position; + for (int r = 0; r < row_block_size; ++r) { + for (int c = 0; c < col_block_size; ++c, ++jac_pos) { + matrix->mutable_rows()[jac_pos] = row_block_pos + r; + matrix->mutable_cols()[jac_pos] = col_block_pos + c; + matrix->mutable_values()[jac_pos] = values_[jac_pos]; + } + } + } + } + matrix->set_num_nonzeros(num_nonzeros_); +} + +// Return a pointer to the block structure. We continue to hold +// ownership of the object though. +const CompressedRowBlockStructure* BlockSparseMatrix::block_structure() + const { + return block_structure_.get(); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void BlockSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { + outer_proto->Clear(); + + BlockSparseMatrixProto* proto = outer_proto->mutable_block_matrix(); + proto->set_num_rows(num_rows_); + proto->set_num_cols(num_cols_); + proto->set_num_nonzeros(num_nonzeros_); + for (int i = 0; i < num_nonzeros_; ++i) { + proto->add_values(values_[i]); + } + BlockStructureToProto(*block_structure_, proto->mutable_block_structure()); +} +#endif + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h new file mode 100644 index 00000000000..b151dd0e248 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h @@ -0,0 +1,142 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Implementation of the SparseMatrix interface for block sparse +// matrices. + +#ifndef CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_ + +#include "ceres/block_structure.h" +#include "ceres/sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; +class TripletSparseMatrix; + +// A further extension of the SparseMatrix interface to support block-oriented +// matrices. The key addition is the RowBlockValues() accessor, which enables +// the lazy block sparse matrix implementation. +class BlockSparseMatrixBase : public SparseMatrix { + public: + BlockSparseMatrixBase() {} + virtual ~BlockSparseMatrixBase() {} + + // Convert this matrix into a triplet sparse matrix. + virtual void ToTripletSparseMatrix(TripletSparseMatrix* matrix) const = 0; + + // Returns a pointer to the block structure. Does not transfer + // ownership. + virtual const CompressedRowBlockStructure* block_structure() const = 0; + + // Returns a pointer to a row of the matrix. The returned array is only valid + // until the next call to RowBlockValues. The caller does not own the result. + // + // The returned array is laid out such that cells on the specified row are + // contiguous in the returned array, though neighbouring cells in row order + // may not be contiguous in the row values. The cell values for cell + // (row_block, cell_block) are found at offset + // + // block_structure()->rows[row_block].cells[cell_block].position + // + virtual const double* RowBlockValues(int row_block_index) const = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrixBase); +}; + +// This class implements the SparseMatrix interface for storing and +// manipulating block sparse matrices. The block structure is stored +// in the CompressedRowBlockStructure object and one is needed to +// initialize the matrix. For details on how the blocks structure of +// the matrix is stored please see the documentation +// +// internal/ceres/block_structure.h +// +class BlockSparseMatrix : public BlockSparseMatrixBase { + public: + // Construct a block sparse matrix with a fully initialized + // CompressedRowBlockStructure objected. The matrix takes over + // ownership of this object and destroys it upon destruction. + // + // TODO(sameeragarwal): Add a function which will validate legal + // CompressedRowBlockStructure objects. + explicit BlockSparseMatrix(CompressedRowBlockStructure* block_structure); + + // Construct a block sparse matrix from a protocol buffer. +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + explicit BlockSparseMatrix(const SparseMatrixProto& proto); +#endif + + BlockSparseMatrix(); + virtual ~BlockSparseMatrix(); + + // Implementation of SparseMatrix interface. + virtual void SetZero(); + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual void SquaredColumnNorm(double* x) const; + virtual void ScaleColumns(const double* scale); + virtual void ToDenseMatrix(Matrix* dense_matrix) const; +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + virtual void ToProto(SparseMatrixProto* proto) const; +#endif + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_cols_; } + virtual int num_nonzeros() const { return num_nonzeros_; } + virtual const double* values() const { return values_.get(); } + virtual double* mutable_values() { return values_.get(); } + + // Implementation of BlockSparseMatrixBase interface. + virtual void ToTripletSparseMatrix(TripletSparseMatrix* matrix) const; + virtual const CompressedRowBlockStructure* block_structure() const; + virtual const double* RowBlockValues(int row_block_index) const { + return values_.get(); + } + + private: + int num_rows_; + int num_cols_; + int max_num_nonzeros_; + int num_nonzeros_; + scoped_array values_; + scoped_ptr block_structure_; + DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrix); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc b/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc new file mode 100644 index 00000000000..5add4f3b94d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc @@ -0,0 +1,92 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_structure.h" +#include "ceres/matrix_proto.h" + +namespace ceres { +namespace internal { + +bool CellLessThan(const Cell& lhs, const Cell& rhs) { + return (lhs.block_id < rhs.block_id); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void ProtoToBlockStructure(const BlockStructureProto &proto, + CompressedRowBlockStructure *block_structure) { + // Decode the column blocks. + block_structure->cols.resize(proto.cols_size()); + for (int i = 0; i < proto.cols_size(); ++i) { + block_structure->cols[i].size = proto.cols(i).size(); + block_structure->cols[i].position = + proto.cols(i).position(); + } + // Decode the row structure. + block_structure->rows.resize(proto.rows_size()); + for (int i = 0; i < proto.rows_size(); ++i) { + const CompressedRowProto &row = proto.rows(i); + block_structure->rows[i].block.size = row.block().size(); + block_structure->rows[i].block.position = row.block().position(); + + // Copy the cells within the row. + block_structure->rows[i].cells.resize(row.cells_size()); + for (int j = 0; j < row.cells_size(); ++j) { + const CellProto &cell = row.cells(j); + block_structure->rows[i].cells[j].block_id = cell.block_id(); + block_structure->rows[i].cells[j].position = cell.position(); + } + } +} + +void BlockStructureToProto(const CompressedRowBlockStructure &block_structure, + BlockStructureProto *proto) { + // Encode the column blocks. + for (int i = 0; i < block_structure.cols.size(); ++i) { + BlockProto *block = proto->add_cols(); + block->set_size(block_structure.cols[i].size); + block->set_position(block_structure.cols[i].position); + } + // Encode the row structure. + for (int i = 0; i < block_structure.rows.size(); ++i) { + CompressedRowProto *row = proto->add_rows(); + BlockProto *block = row->mutable_block(); + block->set_size(block_structure.rows[i].block.size); + block->set_position(block_structure.rows[i].block.position); + for (int j = 0; j < block_structure.rows[i].cells.size(); ++j) { + CellProto *cell = row->add_cells(); + cell->set_block_id(block_structure.rows[i].cells[j].block_id); + cell->set_position(block_structure.rows[i].cells[j].position); + } + } +} +#endif + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_structure.h b/extern/libmv/third_party/ceres/internal/ceres/block_structure.h new file mode 100644 index 00000000000..f509067d216 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_structure.h @@ -0,0 +1,105 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Block structure objects are used to carry information about the +// dense block structure of sparse matrices. The BlockSparseMatrix +// object uses the BlockStructure objects to keep track of the matrix +// structure and operate upon it. This allows us to use more cache +// friendly block oriented linear algebra operations on the matrix +// instead of accessing it one scalar entry at a time. + +#ifndef CERES_INTERNAL_BLOCK_STRUCTURE_H_ +#define CERES_INTERNAL_BLOCK_STRUCTURE_H_ + +#include +#include "ceres/internal/port.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class BlockStructureProto; + +typedef int16 BlockSize; + +struct Block { + Block() : size(-1), position(-1) {} + Block(int size_, int position_) : size(size_), position(position_) {} + + BlockSize size; + int position; // Position along the row/column. +}; + +struct Cell { + Cell() : block_id(-1), position(-1) {} + Cell(int block_id_, int position_) + : block_id(block_id_), position(position_) {} + + // Column or row block id as the case maybe. + int block_id; + // Where in the values array of the jacobian is this cell located. + int position; +}; + +// Order cell by their block_id; +bool CellLessThan(const Cell& lhs, const Cell& rhs); + +struct CompressedList { + Block block; + vector cells; +}; + +typedef CompressedList CompressedRow; +typedef CompressedList CompressedColumn; + +struct CompressedRowBlockStructure { + vector cols; + vector rows; +}; + +struct CompressedColumnBlockStructure { + vector rows; + vector cols; +}; + +// Deserialize the given block structure proto to the given block structure. +// Destroys previous contents of block_structure. +void ProtoToBlockStructure(const BlockStructureProto &proto, + CompressedRowBlockStructure *block_structure); + +// Serialize the given block structure to the given proto. Destroys previous +// contents of proto. +void BlockStructureToProto(const CompressedRowBlockStructure &block_structure, + BlockStructureProto *proto); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_STRUCTURE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc new file mode 100644 index 00000000000..53190ada6fc --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc @@ -0,0 +1,238 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: David Gallup (dgallup@google.com) +// Sameer Agarwal (sameeragarwal@google.com) + +#include "ceres/canonical_views_clustering.h" + +#include +#include "ceres/graph.h" +#include "ceres/collections_port.h" +#include "ceres/map_util.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +typedef HashMap IntMap; +typedef HashSet IntSet; + +class CanonicalViewsClustering { + public: + CanonicalViewsClustering() {} + + // Compute the canonical views clustering of the vertices of the + // graph. centers will contain the vertices that are the identified + // as the canonical views/cluster centers, and membership is a map + // from vertices to cluster_ids. The i^th cluster center corresponds + // to the i^th cluster. It is possible depending on the + // configuration of the clustering algorithm that some of the + // vertices may not be assigned to any cluster. In this case they + // are assigned to a cluster with id = kInvalidClusterId. + void ComputeClustering(const Graph& graph, + const CanonicalViewsClusteringOptions& options, + vector* centers, + IntMap* membership); + + private: + void FindValidViews(IntSet* valid_views) const; + double ComputeClusteringQualityDifference(const int candidate, + const vector& centers) const; + void UpdateCanonicalViewAssignments(const int canonical_view); + void ComputeClusterMembership(const vector& centers, + IntMap* membership) const; + + CanonicalViewsClusteringOptions options_; + const Graph* graph_; + // Maps a view to its representative canonical view (its cluster + // center). + IntMap view_to_canonical_view_; + // Maps a view to its similarity to its current cluster center. + HashMap view_to_canonical_view_similarity_; + DISALLOW_COPY_AND_ASSIGN(CanonicalViewsClustering); +}; + +void ComputeCanonicalViewsClustering( + const Graph& graph, + const CanonicalViewsClusteringOptions& options, + vector* centers, + IntMap* membership) { + time_t start_time = time(NULL); + CanonicalViewsClustering cv; + cv.ComputeClustering(graph, options, centers, membership); + VLOG(2) << "Canonical views clustering time (secs): " + << time(NULL) - start_time; +} + +// Implementation of CanonicalViewsClustering +void CanonicalViewsClustering::ComputeClustering( + const Graph& graph, + const CanonicalViewsClusteringOptions& options, + vector* centers, + IntMap* membership) { + options_ = options; + CHECK_NOTNULL(centers)->clear(); + CHECK_NOTNULL(membership)->clear(); + graph_ = &graph; + + IntSet valid_views; + FindValidViews(&valid_views); + while (valid_views.size() > 0) { + // Find the next best canonical view. + double best_difference = -std::numeric_limits::max(); + int best_view = 0; + + // TODO(sameeragarwal): Make this loop multi-threaded. + for (IntSet::const_iterator view = valid_views.begin(); + view != valid_views.end(); + ++view) { + const double difference = + ComputeClusteringQualityDifference(*view, *centers); + if (difference > best_difference) { + best_difference = difference; + best_view = *view; + } + } + + CHECK_GT(best_difference, -std::numeric_limits::max()); + + // Add canonical view if quality improves, or if minimum is not + // yet met, otherwise break. + if ((best_difference <= 0) && + (centers->size() >= options_.min_views)) { + break; + } + + centers->push_back(best_view); + valid_views.erase(best_view); + UpdateCanonicalViewAssignments(best_view); + } + + ComputeClusterMembership(*centers, membership); +} + +// Return the set of vertices of the graph which have valid vertex +// weights. +void CanonicalViewsClustering::FindValidViews( + IntSet* valid_views) const { + const IntSet& views = graph_->vertices(); + for (IntSet::const_iterator view = views.begin(); + view != views.end(); + ++view) { + if (graph_->VertexWeight(*view) != Graph::InvalidWeight()) { + valid_views->insert(*view); + } + } +} + +// Computes the difference in the quality score if 'candidate' were +// added to the set of canonical views. +double CanonicalViewsClustering::ComputeClusteringQualityDifference( + const int candidate, + const vector& centers) const { + // View score. + double difference = + options_.view_score_weight * graph_->VertexWeight(candidate); + + // Compute how much the quality score changes if the candidate view + // was added to the list of canonical views and its nearest + // neighbors became members of its cluster. + const IntSet& neighbors = graph_->Neighbors(candidate); + for (IntSet::const_iterator neighbor = neighbors.begin(); + neighbor != neighbors.end(); + ++neighbor) { + const double old_similarity = + FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0); + const double new_similarity = graph_->EdgeWeight(*neighbor, candidate); + if (new_similarity > old_similarity) { + difference += new_similarity - old_similarity; + } + } + + // Number of views penalty. + difference -= options_.size_penalty_weight; + + // Orthogonality. + for (int i = 0; i < centers.size(); ++i) { + difference -= options_.similarity_penalty_weight * + graph_->EdgeWeight(centers[i], candidate); + } + + return difference; +} + +// Reassign views if they're more similar to the new canonical view. +void CanonicalViewsClustering::UpdateCanonicalViewAssignments( + const int canonical_view) { + const IntSet& neighbors = graph_->Neighbors(canonical_view); + for (IntSet::const_iterator neighbor = neighbors.begin(); + neighbor != neighbors.end(); + ++neighbor) { + const double old_similarity = + FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0); + const double new_similarity = + graph_->EdgeWeight(*neighbor, canonical_view); + if (new_similarity > old_similarity) { + view_to_canonical_view_[*neighbor] = canonical_view; + view_to_canonical_view_similarity_[*neighbor] = new_similarity; + } + } +} + +// Assign a cluster id to each view. +void CanonicalViewsClustering::ComputeClusterMembership( + const vector& centers, + IntMap* membership) const { + CHECK_NOTNULL(membership)->clear(); + + // The i^th cluster has cluster id i. + IntMap center_to_cluster_id; + for (int i = 0; i < centers.size(); ++i) { + center_to_cluster_id[centers[i]] = i; + } + + static const int kInvalidClusterId = -1; + + const IntSet& views = graph_->vertices(); + for (IntSet::const_iterator view = views.begin(); + view != views.end(); + ++view) { + IntMap::const_iterator it = + view_to_canonical_view_.find(*view); + int cluster_id = kInvalidClusterId; + if (it != view_to_canonical_view_.end()) { + cluster_id = FindOrDie(center_to_cluster_id, it->second); + } + + InsertOrDie(membership, *view, cluster_id); + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h new file mode 100644 index 00000000000..2d1eb403995 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h @@ -0,0 +1,133 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// An implementation of the Canonical Views clustering algorithm from +// "Scene Summarization for Online Image Collections", Ian Simon, Noah +// Snavely, Steven M. Seitz, ICCV 2007. +// +// More details can be found at +// http://grail.cs.washington.edu/projects/canonview/ +// +// Ceres uses this algorithm to perform view clustering for +// constructing visibility based preconditioners. + +#ifndef CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ +#define CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ + +#include + +#include +#include "ceres/collections_port.h" +#include "ceres/graph.h" +#include "ceres/map_util.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +class CanonicalViewsClusteringOptions; + +// Compute a partitioning of the vertices of the graph using the +// canonical views clustering algorithm. +// +// In the following we will use the terms vertices and views +// interchangably. Given a weighted Graph G(V,E), the canonical views +// of G are the the set of vertices that best "summarize" the content +// of the graph. If w_ij i s the weight connecting the vertex i to +// vertex j, and C is the set of canonical views. Then the objective +// of the canonical views algorithm is +// +// E[C] = sum_[i in V] max_[j in C] w_ij +// - size_penalty_weight * |C| +// - similarity_penalty_weight * sum_[i in C, j in C, j > i] w_ij +// +// alpha is the size penalty that penalizes large number of canonical +// views. +// +// beta is the similarity penalty that penalizes canonical views that +// are too similar to other canonical views. +// +// Thus the canonical views algorithm tries to find a canonical view +// for each vertex in the graph which best explains it, while trying +// to minimize the number of canonical views and the overlap between +// them. +// +// We further augment the above objective function by allowing for per +// vertex weights, higher weights indicating a higher preference for +// being chosen as a canonical view. Thus if w_i is the vertex weight +// for vertex i, the objective function is then +// +// E[C] = sum_[i in V] max_[j in C] w_ij +// - size_penalty_weight * |C| +// - similarity_penalty_weight * sum_[i in C, j in C, j > i] w_ij +// + view_score_weight * sum_[i in C] w_i +// +// centers will contain the vertices that are the identified +// as the canonical views/cluster centers, and membership is a map +// from vertices to cluster_ids. The i^th cluster center corresponds +// to the i^th cluster. +// +// It is possible depending on the configuration of the clustering +// algorithm that some of the vertices may not be assigned to any +// cluster. In this case they are assigned to a cluster with id = -1; +void ComputeCanonicalViewsClustering( + const Graph& graph, + const CanonicalViewsClusteringOptions& options, + vector* centers, + HashMap* membership); + +struct CanonicalViewsClusteringOptions { + CanonicalViewsClusteringOptions() + : min_views(3), + size_penalty_weight(5.75), + similarity_penalty_weight(100.0), + view_score_weight(0.0) { + } + // The minimum number of canonical views to compute. + int min_views; + + // Penalty weight for the number of canonical views. A higher + // number will result in fewer canonical views. + double size_penalty_weight; + + // Penalty weight for the diversity (orthogonality) of the + // canonical views. A higher number will encourage less similar + // canonical views. + double similarity_penalty_weight; + + // Weight for per-view scores. Lower weight places less + // confidence in the view scores. + double view_score_weight; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/casts.h b/extern/libmv/third_party/ceres/internal/ceres/casts.h new file mode 100644 index 00000000000..99cf2186cc7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/casts.h @@ -0,0 +1,108 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_CASTS_H_ +#define CERES_INTERNAL_CASTS_H_ + +#include +#include // For NULL. + +namespace ceres { + +// Identity metafunction. +template +struct identity_ { + typedef T type; +}; + +// Use implicit_cast as a safe version of static_cast or const_cast +// for implicit conversions. For example: +// - Upcasting in a type hierarchy. +// - Performing arithmetic conversions (int32 to int64, int to double, etc.). +// - Adding const or volatile qualifiers. +// +// In general, implicit_cast can be used to convert this code +// To to = from; +// DoSomething(to); +// to this +// DoSomething(implicit_cast(from)); +// +// base::identity_ is used to make a non-deduced context, which +// forces all callers to explicitly specify the template argument. +template +inline To implicit_cast(typename identity_::type to) { + return to; +} + +// This version of implicit_cast is used when two template arguments +// are specified. It's obsolete and should not be used. +template +inline To implicit_cast(typename identity_::type const &f) { + return f; +} + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. + +template // use like this: down_cast(foo); +inline To down_cast(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + + // TODO(csilvers): This should use COMPILE_ASSERT. + if (false) { + implicit_cast(NULL); + } + + // uses RTTI in dbg and fastbuild. asserts are disabled in opt builds. + assert(f == NULL || dynamic_cast(f) != NULL); // NOLINT + return static_cast(f); +} + +} // namespace ceres + +#endif // CERES_INTERNAL_CASTS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_linear_operator.h b/extern/libmv/third_party/ceres/internal/ceres/cgnr_linear_operator.h new file mode 100644 index 00000000000..f32d8d95c19 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_linear_operator.h @@ -0,0 +1,120 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_ +#define CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_ + +#include +#include "ceres/linear_operator.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +class SparseMatrix; + +// A linear operator which takes a matrix A and a diagonal vector D and +// performs products of the form +// +// (A^T A + D^T D)x +// +// This is used to implement iterative general sparse linear solving with +// conjugate gradients, where A is the Jacobian and D is a regularizing +// parameter. A brief proof that D^T D is the correct regularizer: +// +// Given a regularized least squares problem: +// +// min ||Ax - b||^2 + ||Dx||^2 +// x +// +// First expand into matrix notation: +// +// (Ax - b)^T (Ax - b) + xD^TDx +// +// Then multiply out to get: +// +// = xA^TAx - 2b^T Ax + b^Tb + xD^TDx +// +// Take the derivative: +// +// 0 = 2A^TAx - 2A^T b + 2 D^TDx +// 0 = A^TAx - A^T b + D^TDx +// 0 = (A^TA + D^TD)x - A^T b +// +// Thus, the symmetric system we need to solve for CGNR is +// +// Sx = z +// +// with S = A^TA + D^TD +// and z = A^T b +// +// Note: This class is not thread safe, since it uses some temporary storage. +class CgnrLinearOperator : public LinearOperator { + public: + CgnrLinearOperator(const LinearOperator& A, const double *D) + : A_(A), D_(D), z_(new double[A.num_rows()]) { + } + virtual ~CgnrLinearOperator() {} + + virtual void RightMultiply(const double* x, double* y) const { + std::fill(z_.get(), z_.get() + A_.num_rows(), 0.0); + + // z = Ax + A_.RightMultiply(x, z_.get()); + + // y = y + Atz + A_.LeftMultiply(z_.get(), y); + + // y = y + DtDx + if (D_ != NULL) { + int n = A_.num_cols(); + VectorRef(y, n).array() += ConstVectorRef(D_, n).array().square() * + ConstVectorRef(x, n).array(); + } + } + + virtual void LeftMultiply(const double* x, double* y) const { + RightMultiply(x, y); + } + + virtual int num_rows() const { return A_.num_cols(); } + virtual int num_cols() const { return A_.num_cols(); } + + private: + const LinearOperator& A_; + const double* D_; + scoped_array z_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc new file mode 100644 index 00000000000..ccc8026f9f7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc @@ -0,0 +1,80 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/cgnr_solver.h" + +#include "glog/logging.h" +#include "ceres/linear_solver.h" +#include "ceres/cgnr_linear_operator.h" +#include "ceres/conjugate_gradients_solver.h" +#include "ceres/block_jacobi_preconditioner.h" + +namespace ceres { +namespace internal { + +CgnrSolver::CgnrSolver(const LinearSolver::Options& options) + : options_(options), + jacobi_preconditioner_(NULL) { +} + +LinearSolver::Summary CgnrSolver::Solve( + LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + // Form z = Atb. + scoped_array z(new double[A->num_cols()]); + std::fill(z.get(), z.get() + A->num_cols(), 0.0); + A->LeftMultiply(b, z.get()); + + // Precondition if necessary. + LinearSolver::PerSolveOptions cg_per_solve_options = per_solve_options; + if (options_.preconditioner_type == JACOBI) { + if (jacobi_preconditioner_.get() == NULL) { + jacobi_preconditioner_.reset(new BlockJacobiPreconditioner(*A)); + } + jacobi_preconditioner_->Update(*A, per_solve_options.D); + cg_per_solve_options.preconditioner = jacobi_preconditioner_.get(); + } else if (options_.preconditioner_type != IDENTITY) { + LOG(FATAL) << "CGNR only supports IDENTITY and JACOBI preconditioners."; + } + + // Solve (AtA + DtD)x = z (= Atb). + std::fill(x, x + A->num_cols(), 0.0); + CgnrLinearOperator lhs(*A, per_solve_options.D); + ConjugateGradientsSolver conjugate_gradient_solver(options_); + return conjugate_gradient_solver.Solve(&lhs, + z.get(), + cg_per_solve_options, + x); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h new file mode 100644 index 00000000000..dd36f99006b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h @@ -0,0 +1,66 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_CGNR_SOLVER_H_ +#define CERES_INTERNAL_CGNR_SOLVER_H_ + +#include "ceres/internal/scoped_ptr.h" +#include "ceres/linear_solver.h" + +namespace ceres { +namespace internal { + +class BlockJacobiPreconditioner; + +// A conjugate gradients on the normal equations solver. This directly solves +// for the solution to +// +// (A^T A + D^T D)x = A^T b +// +// as required for solving for x in the least squares sense. Currently only +// block diagonal preconditioning is supported. +class CgnrSolver : public LinearSolver { + public: + explicit CgnrSolver(const LinearSolver::Options& options); + virtual Summary Solve(LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x); + + private: + const LinearSolver::Options options_; + scoped_ptr jacobi_preconditioner_; + DISALLOW_COPY_AND_ASSIGN(CgnrSolver); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CGNR_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h new file mode 100644 index 00000000000..e125f3fffcd --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h @@ -0,0 +1,141 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Portable HashMap and HashSet, and a specialized overload for hashing pairs. + +#ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_ +#define CERES_INTERNAL_COLLECTIONS_PORT_H_ + +#if defined(_MSC_VER) && _MSC_VER <= 1600 +#include +#include +#else +#include +#include +#endif +#include +#include "ceres/integral_types.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +template +struct HashMap : tr1::unordered_map {}; + +template +struct HashSet : tr1::unordered_set {}; + +#ifdef _WIN32 +#define GG_LONGLONG(x) x##I64 +#define GG_ULONGLONG(x) x##UI64 +#else +#define GG_LONGLONG(x) x##LL +#define GG_ULONGLONG(x) x##ULL +#endif + +// The hash function is due to Bob Jenkins (see +// http://burtleburtle.net/bob/hash/index.html). Each mix takes 36 instructions, +// in 18 cycles if you're lucky. On x86 architectures, this requires 45 +// instructions in 27 cycles, if you're lucky. +// +// 32bit version +inline void hash_mix(uint32& a, uint32& b, uint32& c) { + a -= b; a -= c; a ^= (c>>13); + b -= c; b -= a; b ^= (a<<8); + c -= a; c -= b; c ^= (b>>13); + a -= b; a -= c; a ^= (c>>12); + b -= c; b -= a; b ^= (a<<16); + c -= a; c -= b; c ^= (b>>5); + a -= b; a -= c; a ^= (c>>3); + b -= c; b -= a; b ^= (a<<10); + c -= a; c -= b; c ^= (b>>15); +} + +// 64bit version +inline void hash_mix(uint64& a, uint64& b, uint64& c) { + a -= b; a -= c; a ^= (c>>43); + b -= c; b -= a; b ^= (a<<9); + c -= a; c -= b; c ^= (b>>8); + a -= b; a -= c; a ^= (c>>38); + b -= c; b -= a; b ^= (a<<23); + c -= a; c -= b; c ^= (b>>5); + a -= b; a -= c; a ^= (c>>35); + b -= c; b -= a; b ^= (a<<49); + c -= a; c -= b; c ^= (b>>11); +} + +inline uint32 Hash32NumWithSeed(uint32 num, uint32 c) { + // The golden ratio; an arbitrary value. + uint32 b = 0x9e3779b9UL; + hash_mix(num, b, c); + return c; +} + +inline uint64 Hash64NumWithSeed(uint64 num, uint64 c) { + // More of the golden ratio. + uint64 b = GG_ULONGLONG(0xe08c1d668b756f82); + hash_mix(num, b, c); + return c; +} + +} // namespace internal +} // namespace ceres + +// Since on some platforms this is a doubly-nested namespace (std::tr1) and +// others it is not, the entire namespace line must be in a macro. +CERES_HASH_NAMESPACE_START + +// The outrageously annoying specializations below are for portability reasons. +// In short, it's not possible to have two overloads of hash + +// Hasher for STL pairs. Requires hashers for both members to be defined. +template +struct hash > { + size_t operator()(const pair& p) const { + size_t h1 = hash()(p.first); + size_t h2 = hash()(p.second); + // The decision below is at compile time + return (sizeof(h1) <= sizeof(ceres::internal::uint32)) ? + ceres::internal::Hash32NumWithSeed(h1, h2) : + ceres::internal::Hash64NumWithSeed(h1, h2); + } + // Less than operator for MSVC. + bool operator()(const pair& a, + const pair& b) const { + return a < b; + } + static const size_t bucket_size = 4; // These are required by MSVC + static const size_t min_buckets = 8; // 4 and 8 are defaults. +}; + +CERES_HASH_NAMESPACE_END + +#endif // CERES_INTERNAL_COLLECTIONS_PORT_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc new file mode 100644 index 00000000000..aa883b7d353 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc @@ -0,0 +1,201 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/compressed_row_jacobian_writer.h" + +#include "ceres/casts.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/scratch_evaluate_preparer.h" + +namespace ceres { +namespace internal { + +SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { + const vector& residual_blocks = + program_->residual_blocks(); + + int total_num_residuals = program_->NumResiduals(); + int total_num_effective_parameters = program_->NumEffectiveParameters(); + + // Count the number of jacobian nonzeros. + int num_jacobian_nonzeros = 0; + for (int i = 0; i < residual_blocks.size(); ++i) { + ResidualBlock* residual_block = residual_blocks[i]; + const int num_residuals = residual_block->NumResiduals(); + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + num_jacobian_nonzeros += num_residuals * parameter_block->LocalSize(); + } + } + } + + // Allocate storage for the jacobian with some extra space at the end. + // Allocate more space than needed to store the jacobian so that when the LM + // algorithm adds the diagonal, no reallocation is necessary. This reduces + // peak memory usage significantly. + CompressedRowSparseMatrix* jacobian = + new CompressedRowSparseMatrix( + total_num_residuals, + total_num_effective_parameters, + num_jacobian_nonzeros + total_num_effective_parameters); + + // At this stage, the CompressedSparseMatrix is an invalid state. But this + // seems to be the only way to construct it without doing a memory copy. + int* rows = jacobian->mutable_rows(); + int* cols = jacobian->mutable_cols(); + int row_pos = 0; + rows[0] = 0; + for (int i = 0; i < residual_blocks.size(); ++i) { + const ResidualBlock* residual_block = residual_blocks[i]; + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + + // Count the number of derivatives for a row of this residual block and + // build a list of active parameter block indices. + int num_derivatives = 0; + vector parameter_indices; + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + parameter_indices.push_back(parameter_block->index()); + num_derivatives += parameter_block->LocalSize(); + } + } + + // Sort the parameters by their position in the state vector. + sort(parameter_indices.begin(), parameter_indices.end()); + CHECK(unique(parameter_indices.begin(), parameter_indices.end()) == + parameter_indices.end()) + << "Ceres internal error: " + << "Duplicate parameter blocks detected in a cost function. " + << "This should never happen. Please report this to " + << "the Ceres developers."; + + // Update the row indices. + const int num_residuals = residual_block->NumResiduals(); + for (int j = 0; j < num_residuals; ++j) { + rows[row_pos + j + 1] = rows[row_pos + j] + num_derivatives; + } + + // Iterate over parameter blocks in the order which they occur in the + // parameter vector. This code mirrors that in Write(), where jacobian + // values are updated. + int col_pos = 0; + for (int j = 0; j < parameter_indices.size(); ++j) { + ParameterBlock* parameter_block = + program_->parameter_blocks()[parameter_indices[j]]; + const int parameter_block_size = parameter_block->LocalSize(); + + for (int r = 0; r < num_residuals; ++r) { + // This is the position in the values array of the jacobian where this + // row of the jacobian block should go. + const int column_block_begin = rows[row_pos + r] + col_pos; + + for (int c = 0; c < parameter_block_size; ++c) { + cols[column_block_begin + c] = parameter_block->delta_offset() + c; + } + } + col_pos += parameter_block_size; + } + row_pos += num_residuals; + } + + CHECK_EQ(num_jacobian_nonzeros, rows[total_num_residuals]); + return jacobian; +} + +void CompressedRowJacobianWriter::Write(int residual_id, + int residual_offset, + double **jacobians, + SparseMatrix* base_jacobian) { + CompressedRowSparseMatrix* jacobian = + down_cast(base_jacobian); + + double* jacobian_values = jacobian->mutable_values(); + const int* jacobian_rows = jacobian->rows(); + + const ResidualBlock* residual_block = + program_->residual_blocks()[residual_id]; + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + const int num_residuals = residual_block->NumResiduals(); + + // It is necessary to determine the order of the jacobian blocks before + // copying them into the CompressedRowSparseMatrix. Just because a cost + // function uses parameter blocks 1 after 2 in its arguments does not mean + // that the block 1 occurs before block 2 in the column layout of the + // jacobian. Thus, determine the order by sorting the jacobian blocks by their + // position in the state vector. + vector > evaluated_jacobian_blocks; + for (int j = 0; j < num_parameter_blocks; ++j) { + const ParameterBlock* parameter_block = + residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + evaluated_jacobian_blocks.push_back( + make_pair(parameter_block->index(), j)); + } + } + sort(evaluated_jacobian_blocks.begin(), evaluated_jacobian_blocks.end()); + + // Where in the current row does the jacobian for a parameter block begin. + int col_pos = 0; + + // Iterate over the jacobian blocks in increasing order of their + // positions in the reduced parameter vector. + for (int i = 0; i < evaluated_jacobian_blocks.size(); ++i) { + const ParameterBlock* parameter_block = + program_->parameter_blocks()[evaluated_jacobian_blocks[i].first]; + const int argument = evaluated_jacobian_blocks[i].second; + const int parameter_block_size = parameter_block->LocalSize(); + + // Copy one row of the jacobian block at a time. + for (int r = 0; r < num_residuals; ++r) { + // Position of the r^th row of the current jacobian block. + const double* block_row_begin = + jacobians[argument] + r * parameter_block_size; + + // Position in the values array of the jacobian where this + // row of the jacobian block should go. + double* column_block_begin = + jacobian_values + jacobian_rows[residual_offset + r] + col_pos; + + copy(block_row_begin, + block_row_begin + parameter_block_size, + column_block_begin); + } + col_pos += parameter_block_size; + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.h b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.h new file mode 100644 index 00000000000..c103165eaf1 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.h @@ -0,0 +1,75 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A jacobian writer that directly writes to compressed row sparse matrices. + +#ifndef CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_ +#define CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_ + +#include "ceres/evaluator.h" +#include "ceres/scratch_evaluate_preparer.h" + +namespace ceres { +namespace internal { + +class Program; +class SparseMatrix; + +class CompressedRowJacobianWriter { + public: + CompressedRowJacobianWriter(Evaluator::Options /* ignored */, + Program* program) + : program_(program) { + } + + // JacobianWriter interface. + + // Since the compressed row matrix has different layout than that assumed by + // the cost functions, use scratch space to store the jacobians temporarily + // then copy them over to the larger jacobian in the Write() function. + ScratchEvaluatePreparer* CreateEvaluatePreparers(int num_threads) { + return ScratchEvaluatePreparer::Create(*program_, num_threads); + } + + SparseMatrix* CreateJacobian() const; + + void Write(int residual_id, + int residual_offset, + double **jacobians, + SparseMatrix* base_jacobian); + + private: + Program* program_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc new file mode 100644 index 00000000000..8fd568ffcc3 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc @@ -0,0 +1,325 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/compressed_row_sparse_matrix.h" + +#include +#include +#include "ceres/matrix_proto.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { +namespace { + +// Helper functor used by the constructor for reordering the contents +// of a TripletSparseMatrix. +struct RowColLessThan { + RowColLessThan(const int* rows, const int* cols) + : rows(rows), cols(cols) { + } + + bool operator()(const int x, const int y) const { + if (rows[x] == rows[y]) { + return (cols[x] < cols[y]); + } + return (rows[x] < rows[y]); + } + + const int* rows; + const int* cols; +}; + +} // namespace + +// This constructor gives you a semi-initialized CompressedRowSparseMatrix. +CompressedRowSparseMatrix::CompressedRowSparseMatrix(int num_rows, + int num_cols, + int max_num_nonzeros) { + num_rows_ = num_rows; + num_cols_ = num_cols; + max_num_nonzeros_ = max_num_nonzeros; + + VLOG(1) << "# of rows: " << num_rows_ << " # of columns: " << num_cols_ + << " max_num_nonzeros: " << max_num_nonzeros_ + << ". Allocating " << (num_rows_ + 1) * sizeof(int) + // NOLINT + max_num_nonzeros_ * sizeof(int) + // NOLINT + max_num_nonzeros_ * sizeof(double); // NOLINT + + rows_.reset(new int[num_rows_ + 1]); + cols_.reset(new int[max_num_nonzeros_]); + values_.reset(new double[max_num_nonzeros_]); + + fill(rows_.get(), rows_.get() + num_rows_ + 1, 0); + fill(cols_.get(), cols_.get() + max_num_nonzeros_, 0); + fill(values_.get(), values_.get() + max_num_nonzeros_, 0); +} + +CompressedRowSparseMatrix::CompressedRowSparseMatrix( + const TripletSparseMatrix& m) { + num_rows_ = m.num_rows(); + num_cols_ = m.num_cols(); + max_num_nonzeros_ = m.max_num_nonzeros(); + + // index is the list of indices into the TripletSparseMatrix m. + vector index(m.num_nonzeros(), 0); + for (int i = 0; i < m.num_nonzeros(); ++i) { + index[i] = i; + } + + // Sort index such that the entries of m are ordered by row and ties + // are broken by column. + sort(index.begin(), index.end(), RowColLessThan(m.rows(), m.cols())); + + VLOG(1) << "# of rows: " << num_rows_ << " # of columns: " << num_cols_ + << " max_num_nonzeros: " << max_num_nonzeros_ + << ". Allocating " << (num_rows_ + 1) * sizeof(int) + // NOLINT + max_num_nonzeros_ * sizeof(int) + // NOLINT + max_num_nonzeros_ * sizeof(double); // NOLINT + + rows_.reset(new int[num_rows_ + 1]); + cols_.reset(new int[max_num_nonzeros_]); + values_.reset(new double[max_num_nonzeros_]); + + // rows_ = 0 + fill(rows_.get(), rows_.get() + num_rows_ + 1, 0); + + // Copy the contents of the cols and values array in the order given + // by index and count the number of entries in each row. + for (int i = 0; i < m.num_nonzeros(); ++i) { + const int idx = index[i]; + ++rows_[m.rows()[idx] + 1]; + cols_[i] = m.cols()[idx]; + values_[i] = m.values()[idx]; + } + + // Find the cumulative sum of the row counts. + for (int i = 1; i < num_rows_ + 1; ++i) { + rows_[i] += rows_[i-1]; + } + + CHECK_EQ(num_nonzeros(), m.num_nonzeros()); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +CompressedRowSparseMatrix::CompressedRowSparseMatrix( + const SparseMatrixProto& outer_proto) { + CHECK(outer_proto.has_compressed_row_matrix()); + + const CompressedRowSparseMatrixProto& proto = + outer_proto.compressed_row_matrix(); + + num_rows_ = proto.num_rows(); + num_cols_ = proto.num_cols(); + + rows_.reset(new int[proto.rows_size()]); + cols_.reset(new int[proto.cols_size()]); + values_.reset(new double[proto.values_size()]); + + for (int i = 0; i < proto.rows_size(); ++i) { + rows_[i] = proto.rows(i); + } + + CHECK_EQ(proto.rows_size(), num_rows_ + 1); + CHECK_EQ(proto.cols_size(), proto.values_size()); + CHECK_EQ(proto.cols_size(), rows_[num_rows_]); + + for (int i = 0; i < proto.cols_size(); ++i) { + cols_[i] = proto.cols(i); + values_[i] = proto.values(i); + } + + max_num_nonzeros_ = proto.cols_size(); +} +#endif + +CompressedRowSparseMatrix::CompressedRowSparseMatrix(const double* diagonal, + int num_rows) { + CHECK_NOTNULL(diagonal); + + num_rows_ = num_rows; + num_cols_ = num_rows; + max_num_nonzeros_ = num_rows; + + rows_.reset(new int[num_rows_ + 1]); + cols_.reset(new int[num_rows_]); + values_.reset(new double[num_rows_]); + + rows_[0] = 0; + for (int i = 0; i < num_rows_; ++i) { + cols_[i] = i; + values_[i] = diagonal[i]; + rows_[i + 1] = i + 1; + } + + CHECK_EQ(num_nonzeros(), num_rows); +} + +CompressedRowSparseMatrix::~CompressedRowSparseMatrix() { +} + +void CompressedRowSparseMatrix::SetZero() { + fill(values_.get(), values_.get() + num_nonzeros(), 0.0); +} + +void CompressedRowSparseMatrix::RightMultiply(const double* x, + double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + + for (int r = 0; r < num_rows_; ++r) { + for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) { + y[r] += values_[idx] * x[cols_[idx]]; + } + } +} + +void CompressedRowSparseMatrix::LeftMultiply(const double* x, double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + + for (int r = 0; r < num_rows_; ++r) { + for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) { + y[cols_[idx]] += values_[idx] * x[r]; + } + } +} + +void CompressedRowSparseMatrix::SquaredColumnNorm(double* x) const { + CHECK_NOTNULL(x); + + fill(x, x + num_cols_, 0.0); + for (int idx = 0; idx < rows_[num_rows_]; ++idx) { + x[cols_[idx]] += values_[idx] * values_[idx]; + } +} + +void CompressedRowSparseMatrix::ScaleColumns(const double* scale) { + CHECK_NOTNULL(scale); + + for (int idx = 0; idx < rows_[num_rows_]; ++idx) { + values_[idx] *= scale[cols_[idx]]; + } +} + +void CompressedRowSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { + CHECK_NOTNULL(dense_matrix); + dense_matrix->resize(num_rows_, num_cols_); + dense_matrix->setZero(); + + for (int r = 0; r < num_rows_; ++r) { + for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) { + (*dense_matrix)(r, cols_[idx]) = values_[idx]; + } + } +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void CompressedRowSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { + CHECK_NOTNULL(outer_proto); + + outer_proto->Clear(); + CompressedRowSparseMatrixProto* proto + = outer_proto->mutable_compressed_row_matrix(); + + proto->set_num_rows(num_rows_); + proto->set_num_cols(num_cols_); + + for (int r = 0; r < num_rows_ + 1; ++r) { + proto->add_rows(rows_[r]); + } + + for (int idx = 0; idx < rows_[num_rows_]; ++idx) { + proto->add_cols(cols_[idx]); + proto->add_values(values_[idx]); + } +} +#endif + +void CompressedRowSparseMatrix::DeleteRows(int delta_rows) { + CHECK_GE(delta_rows, 0); + CHECK_LE(delta_rows, num_rows_); + + int new_num_rows = num_rows_ - delta_rows; + + num_rows_ = new_num_rows; + int* new_rows = new int[num_rows_ + 1]; + copy(rows_.get(), rows_.get() + num_rows_ + 1, new_rows); + rows_.reset(new_rows); +} + +void CompressedRowSparseMatrix::AppendRows(const CompressedRowSparseMatrix& m) { + CHECK_EQ(m.num_cols(), num_cols_); + + // Check if there is enough space. If not, then allocate new arrays + // to hold the combined matrix and copy the contents of this matrix + // into it. + if (max_num_nonzeros_ < num_nonzeros() + m.num_nonzeros()) { + int new_max_num_nonzeros = num_nonzeros() + m.num_nonzeros(); + + VLOG(1) << "Reallocating " << sizeof(int) * new_max_num_nonzeros; // NOLINT + + int* new_cols = new int[new_max_num_nonzeros]; + copy(cols_.get(), cols_.get() + max_num_nonzeros_, new_cols); + cols_.reset(new_cols); + + double* new_values = new double[new_max_num_nonzeros]; + copy(values_.get(), values_.get() + max_num_nonzeros_, new_values); + values_.reset(new_values); + + max_num_nonzeros_ = new_max_num_nonzeros; + } + + // Copy the contents of m into this matrix. + copy(m.cols(), m.cols() + m.num_nonzeros(), cols_.get() + num_nonzeros()); + copy(m.values(), + m.values() + m.num_nonzeros(), + values_.get() + num_nonzeros()); + + // Create the new rows array to hold the enlarged matrix. + int* new_rows = new int[num_rows_ + m.num_rows() + 1]; + // The first num_rows_ entries are the same + copy(rows_.get(), rows_.get() + num_rows_, new_rows); + + // new_rows = [rows_, m.row() + rows_[num_rows_]] + fill(new_rows + num_rows_, + new_rows + num_rows_ + m.num_rows() + 1, + rows_[num_rows_]); + + for (int r = 0; r < m.num_rows() + 1; ++r) { + new_rows[num_rows_ + r] += m.rows()[r]; + } + + rows_.reset(new_rows); + num_rows_ += m.num_rows(); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h new file mode 100644 index 00000000000..43712a86640 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h @@ -0,0 +1,129 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ + +#include +#include "ceres/sparse_matrix.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/macros.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; + +class CompressedRowSparseMatrix : public SparseMatrix { + public: + // Build a matrix with the same content as the TripletSparseMatrix + // m. TripletSparseMatrix objects are easier to construct + // incrementally, so we use them to initialize SparseMatrix + // objects. + // + // We assume that m does not have any repeated entries. + explicit CompressedRowSparseMatrix(const TripletSparseMatrix& m); +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + explicit CompressedRowSparseMatrix(const SparseMatrixProto& proto); +#endif + + // Use this constructor only if you know what you are doing. This + // creates a "blank" matrix with the appropriate amount of memory + // allocated. However, the object itself is in an inconsistent state + // as the rows and cols matrices do not match the values of + // num_rows, num_cols and max_num_nonzeros. + // + // The use case for this constructor is that when the user knows the + // size of the matrix to begin with and wants to update the layout + // manually, instead of going via the indirect route of first + // constructing a TripletSparseMatrix, which leads to more than + // double the peak memory usage. + CompressedRowSparseMatrix(int num_rows, + int num_cols, + int max_num_nonzeros); + + // Build a square sparse diagonal matrix with num_rows rows and + // columns. The diagonal m(i,i) = diagonal(i); + CompressedRowSparseMatrix(const double* diagonal, int num_rows); + + virtual ~CompressedRowSparseMatrix(); + + // SparseMatrix interface. + virtual void SetZero(); + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual void SquaredColumnNorm(double* x) const; + virtual void ScaleColumns(const double* scale); + + virtual void ToDenseMatrix(Matrix* dense_matrix) const; +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + virtual void ToProto(SparseMatrixProto* proto) const; +#endif + + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_cols_; } + virtual int num_nonzeros() const { return rows_[num_rows_]; } + virtual const double* values() const { return values_.get(); } + virtual double* mutable_values() { return values_.get(); } + + // Delete the bottom delta_rows. + // num_rows -= delta_rows + void DeleteRows(int delta_rows); + + // Append the contents of m to the bottom of this matrix. m must + // have the same number of columns as this matrix. + void AppendRows(const CompressedRowSparseMatrix& m); + + // Low level access methods that expose the structure of the matrix. + const int* cols() const { return cols_.get(); } + int* mutable_cols() { return cols_.get(); } + + const int* rows() const { return rows_.get(); } + int* mutable_rows() { return rows_.get(); } + + private: + scoped_array cols_; + scoped_array rows_; + scoped_array values_; + + int num_rows_; + int num_cols_; + + int max_num_nonzeros_; + + DISALLOW_COPY_AND_ASSIGN(CompressedRowSparseMatrix); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc new file mode 100644 index 00000000000..ca80bfb9c9d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc @@ -0,0 +1,130 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: wjr@google.com (William Rucklidge) +// +// This file contains the implementation of the conditioned cost function. + +#include "ceres/conditioned_cost_function.h" + +#include + +#include +#include "ceres/stl_util.h" +#include "ceres/internal/eigen.h" +#include "ceres/types.h" + +namespace ceres { + +// This cost function has the same dimensions (parameters, residuals) as +// the one it's wrapping. +ConditionedCostFunction::ConditionedCostFunction( + CostFunction* wrapped_cost_function, + const vector& conditioners, + Ownership ownership) + : wrapped_cost_function_(wrapped_cost_function), + conditioners_(conditioners), + ownership_(ownership) { + // Set up our dimensions. + set_num_residuals(wrapped_cost_function_->num_residuals()); + *mutable_parameter_block_sizes() = + wrapped_cost_function_->parameter_block_sizes(); + + // Sanity-check the conditioners' dimensions. + CHECK_EQ(wrapped_cost_function_->num_residuals(), conditioners_.size()); + for (int i = 0; i < wrapped_cost_function_->num_residuals(); i++) { + if (conditioners[i]) { + CHECK_EQ(1, conditioners[i]->num_residuals()); + CHECK_EQ(1, conditioners[i]->parameter_block_sizes().size()); + CHECK_EQ(1, conditioners[i]->parameter_block_sizes()[0]); + } + } +} + +ConditionedCostFunction::~ConditionedCostFunction() { + if (ownership_ == TAKE_OWNERSHIP) { + STLDeleteElements(&conditioners_); + } else { + wrapped_cost_function_.release(); + } +} + +bool ConditionedCostFunction::Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + bool success = wrapped_cost_function_->Evaluate(parameters, residuals, + jacobians); + if (!success) { + return false; + } + + for (int r = 0; r < wrapped_cost_function_->num_residuals(); r++) { + // On output, we want to have + // residuals[r] = conditioners[r](wrapped_residuals[r]) + // For parameter block i, column c, + // jacobians[i][r*parameter_block_size_[i] + c] = + // = d residual[r] / d parameters[i][c] + // = conditioners[r]'(wrapped_residuals[r]) * + // d wrapped_residuals[r] / d parameters[i][c] + if (conditioners_[r]) { + double conditioner_derivative; + double* conditioner_derivative_pointer = &conditioner_derivative; + double** conditioner_derivative_pointer2 = + &conditioner_derivative_pointer; + if (!jacobians) { + conditioner_derivative_pointer2 = NULL; + } + + double unconditioned_residual = residuals[r]; + double* parameter_pointer = &unconditioned_residual; + success = conditioners_[r]->Evaluate(¶meter_pointer, + &residuals[r], + conditioner_derivative_pointer2); + if (!success) { + return false; + } + + if (jacobians) { + for (int i = 0; + i < wrapped_cost_function_->parameter_block_sizes().size(); + i++) { + if (jacobians[i]) { + int parameter_block_size = + wrapped_cost_function_->parameter_block_sizes()[i]; + VectorRef jacobian_row(jacobians[i] + r * parameter_block_size, + parameter_block_size, 1); + jacobian_row *= conditioner_derivative; + } + } + } + } + } + return true; +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc new file mode 100644 index 00000000000..75f9e043fa5 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc @@ -0,0 +1,233 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// A preconditioned conjugate gradients solver +// (ConjugateGradientsSolver) for positive semidefinite linear +// systems. +// +// We have also augmented the termination criterion used by this +// solver to support not just residual based termination but also +// termination based on decrease in the value of the quadratic model +// that CG optimizes. + +#include "ceres/conjugate_gradients_solver.h" + +#include +#include +#include +#include "ceres/linear_operator.h" +#include "ceres/internal/eigen.h" +#include "ceres/types.h" +#include "ceres/jet.h" + +namespace ceres { +namespace internal { +namespace { + +bool IsZeroOrInfinity(double x) { + return ((x == 0.0) || (isinf(x))); +} + +// Constant used in the MATLAB implementation ~ 2 * eps. +const double kEpsilon = 2.2204e-16; + +} // namespace + +ConjugateGradientsSolver::ConjugateGradientsSolver( + const LinearSolver::Options& options) + : options_(options) { +} + +LinearSolver::Summary ConjugateGradientsSolver::Solve( + LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + CHECK_NOTNULL(A); + CHECK_NOTNULL(x); + CHECK_NOTNULL(b); + CHECK_EQ(A->num_rows(), A->num_cols()); + + LinearSolver::Summary summary; + summary.termination_type = MAX_ITERATIONS; + summary.num_iterations = 0; + + int num_cols = A->num_cols(); + VectorRef xref(x, num_cols); + ConstVectorRef bref(b, num_cols); + + double norm_b = bref.norm(); + if (norm_b == 0.0) { + xref.setZero(); + summary.termination_type = TOLERANCE; + return summary; + } + + Vector r(num_cols); + Vector p(num_cols); + Vector z(num_cols); + Vector tmp(num_cols); + + double tol_r = per_solve_options.r_tolerance * norm_b; + + tmp.setZero(); + A->RightMultiply(x, tmp.data()); + r = bref - tmp; + double norm_r = r.norm(); + + if (norm_r <= tol_r) { + summary.termination_type = TOLERANCE; + return summary; + } + + double rho = 1.0; + + // Initial value of the quadratic model Q = x'Ax - 2 * b'x. + double Q0 = -1.0 * xref.dot(bref + r); + + for (summary.num_iterations = 1; + summary.num_iterations < options_.max_num_iterations; + ++summary.num_iterations) { + VLOG(2) << "cg iteration " << summary.num_iterations; + + // Apply preconditioner + if (per_solve_options.preconditioner != NULL) { + z.setZero(); + per_solve_options.preconditioner->RightMultiply(r.data(), z.data()); + } else { + z = r; + } + + double last_rho = rho; + rho = r.dot(z); + + if (IsZeroOrInfinity(rho)) { + LOG(ERROR) << "Numerical failure. rho = " << rho; + summary.termination_type = FAILURE; + break; + }; + + if (summary.num_iterations == 1) { + p = z; + } else { + double beta = rho / last_rho; + if (IsZeroOrInfinity(beta)) { + LOG(ERROR) << "Numerical failure. beta = " << beta; + summary.termination_type = FAILURE; + break; + } + p = z + beta * p; + } + + Vector& q = z; + q.setZero(); + A->RightMultiply(p.data(), q.data()); + double pq = p.dot(q); + + if ((pq <= 0) || isinf(pq)) { + LOG(ERROR) << "Numerical failure. pq = " << pq; + summary.termination_type = FAILURE; + break; + } + + double alpha = rho / pq; + if (isinf(alpha)) { + LOG(ERROR) << "Numerical failure. alpha " << alpha; + summary.termination_type = FAILURE; + break; + } + + xref = xref + alpha * p; + + // Ideally we would just use the update r = r - alpha*q to keep + // track of the residual vector. However this estimate tends to + // drift over time due to round off errors. Thus every + // residual_reset_period iterations, we calculate the residual as + // r = b - Ax. We do not do this every iteration because this + // requires an additional matrix vector multiply which would + // double the complexity of the CG algorithm. + if (summary.num_iterations % options_.residual_reset_period == 0) { + tmp.setZero(); + A->RightMultiply(x, tmp.data()); + r = bref - tmp; + } else { + r = r - alpha * q; + } + + // Quadratic model based termination. + // Q1 = x'Ax - 2 * b' x. + double Q1 = -1.0 * xref.dot(bref + r); + + // For PSD matrices A, let + // + // Q(x) = x'Ax - 2b'x + // + // be the cost of the quadratic function defined by A and b. Then, + // the solver terminates at iteration i if + // + // i * (Q(x_i) - Q(x_i-1)) / Q(x_i) < q_tolerance. + // + // This termination criterion is more useful when using CG to + // solve the Newton step. This particular convergence test comes + // from Stephen Nash's work on truncated Newton + // methods. References: + // + // 1. Stephen G. Nash & Ariela Sofer, Assessing A Search + // Direction Within A Truncated Newton Method, Operation + // Research Letters 9(1990) 219-221. + // + // 2. Stephen G. Nash, A Survey of Truncated Newton Methods, + // Journal of Computational and Applied Mathematics, + // 124(1-2), 45-59, 2000. + // + double zeta = summary.num_iterations * (Q1 - Q0) / Q1; + VLOG(2) << "Q termination: zeta " << zeta + << " " << per_solve_options.q_tolerance; + if (zeta < per_solve_options.q_tolerance) { + summary.termination_type = TOLERANCE; + break; + } + Q0 = Q1; + + // Residual based termination. + norm_r = r. norm(); + VLOG(2) << "R termination: norm_r " << norm_r + << " " << tol_r; + if (norm_r <= tol_r) { + summary.termination_type = TOLERANCE; + break; + } + } + + return summary; +}; + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h new file mode 100644 index 00000000000..57f99e31db7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h @@ -0,0 +1,74 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Preconditioned Conjugate Gradients based solver for positive +// semidefinite linear systems. + +#ifndef CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_ +#define CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_ + +#include "ceres/linear_solver.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +class LinearOperator; + +// This class implements the now classical Conjugate Gradients +// algorithm of Hestenes & Stiefel for solving postive semidefinite +// linear sytems. Optionally it can use a preconditioner also to +// reduce the condition number of the linear system and improve the +// convergence rate. Modern references for Conjugate Gradients are the +// books by Yousef Saad and Trefethen & Bau. This implementation of CG +// has been augmented with additional termination tests that are +// needed for forcing early termination when used as part of an +// inexact Newton solver. +// +// For more details see the documentation for +// LinearSolver::PerSolveOptions::r_tolerance and +// LinearSolver::PerSolveOptions::q_tolerance in linear_solver.h. +class ConjugateGradientsSolver : public LinearSolver { + public: + explicit ConjugateGradientsSolver(const LinearSolver::Options& options); + virtual Summary Solve(LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x); + + private: + const LinearSolver::Options options_; + DISALLOW_COPY_AND_ASSIGN(ConjugateGradientsSolver); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc new file mode 100644 index 00000000000..4ca2c6f6c86 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc @@ -0,0 +1,125 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/corrector.h" + +#include +#include +#include +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +Corrector::Corrector(double sq_norm, const double rho[3]) { + CHECK_GE(sq_norm, 0.0); + CHECK_GT(rho[1], 0.0); + sqrt_rho1_ = sqrt(rho[1]); + + // If sq_norm = 0.0, the correction becomes trivial, the residual + // and the jacobian are scaled by the squareroot of the derivative + // of rho. Handling this case explicitly avoids the divide by zero + // error that would occur below. + // + // The case where rho'' < 0 also gets special handling. Technically + // it shouldn't, and the computation of the scaling should proceed + // as below, however we found in experiments that applying the + // curvature correction when rho'' < 0, which is the case when we + // are in the outlier region slows down the convergence of the + // algorithm significantly. + // + // Thus, we have divided the action of the robustifier into two + // parts. In the inliner region, we do the full second order + // correction which re-wights the gradient of the function by the + // square root of the derivative of rho, and the Gauss-Newton + // Hessian gets both the scaling and the rank-1 curvature + // correction. Normaly, alpha is upper bounded by one, but with this + // change, alpha is bounded above by zero. + // + // Empirically we have observed that the full Triggs correction and + // the clamped correction both start out as very good approximations + // to the loss function when we are in the convex part of the + // function, but as the function starts transitioning from convex to + // concave, the Triggs approximation diverges more and more and + // ultimately becomes linear. The clamped Triggs model however + // remains quadratic. + // + // The reason why the Triggs approximation becomes so poor is + // because the curvature correction that it applies to the gauss + // newton hessian goes from being a full rank correction to a rank + // deficient correction making the inversion of the Hessian fraught + // with all sorts of misery and suffering. + // + // The clamped correction retains its quadratic nature and inverting it + // is always well formed. + if ((sq_norm == 0.0) || (rho[2] <= 0.0)) { + residual_scaling_ = sqrt_rho1_; + alpha_sq_norm_ = 0.0; + return; + } + + // Calculate the smaller of the two solutions to the equation + // + // 0.5 * alpha^2 - alpha - rho'' / rho' * z'z = 0. + // + // Start by calculating the discriminant D. + const double D = 1.0 + 2.0 * sq_norm*rho[2] / rho[1]; + + // Since both rho[1] and rho[2] are guaranteed to be positive at + // this point, we know that D > 1.0. + + const double alpha = 1.0 - sqrt(D); + + // Calculate the constants needed by the correction routines. + residual_scaling_ = sqrt_rho1_ / (1 - alpha); + alpha_sq_norm_ = alpha / sq_norm; +} + +void Corrector::CorrectResiduals(int nrow, double* residuals) { + DCHECK(residuals != NULL); + VectorRef r_ref(residuals, nrow); + // Equation 11 in BANS. + r_ref *= residual_scaling_; +} + +void Corrector::CorrectJacobian(int nrow, int ncol, + double* residuals, double* jacobian) { + DCHECK(residuals != NULL); + DCHECK(jacobian != NULL); + ConstVectorRef r_ref(residuals, nrow); + MatrixRef j_ref(jacobian, nrow, ncol); + + // Equation 11 in BANS. + j_ref = sqrt_rho1_ * (j_ref - alpha_sq_norm_ * + r_ref * (r_ref.transpose() * j_ref)); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/corrector.h b/extern/libmv/third_party/ceres/internal/ceres/corrector.h new file mode 100644 index 00000000000..9914641cb01 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/corrector.h @@ -0,0 +1,88 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Class definition for the object that is responsible for applying a +// second order correction to the Gauss-Newton based on the ideas in +// BANS by Triggs et al. + +#ifndef CERES_INTERNAL_CORRECTOR_H_ +#define CERES_INTERNAL_CORRECTOR_H_ + +namespace ceres { +namespace internal { + +// Corrector is responsible for applying the second order correction +// to the residual and jacobian of a least squares problem based on a +// radial robust loss. +// +// The key idea here is to look at the expressions for the robustified +// gauss newton approximation and then take its squareroot to get the +// corresponding corrections to the residual and jacobian. For the +// full expressions see Eq. 10 and 11 in BANS by Triggs et al. +class Corrector { + public: + // The constructor takes the squared norm, the value, the first and + // second derivatives of the LossFunction. It precalculates some of + // the constants that are needed to apply the correction. The + // correction constant alpha is constrained to be smaller than 1, if + // it becomes larger than 1, then it will reverse the sign of the + // residual and the correction. If alpha is equal to 1 will result + // in a divide by zero error. Thus we constrain alpha to be upper + // bounded by 1 - epsilon_. + // + // rho[1] needs to be positive. The constructor will crash if this + // condition is not met. + // + // In practical use CorrectJacobian should always be called before + // CorrectResidual, because the jacobian correction depends on the + // value of the uncorrected residual values. + explicit Corrector(double sq_norm, const double rho[3]); + + // residuals *= sqrt(rho[1]) / (1 - alpha) + void CorrectResiduals(int nrow, double* residuals); + + // jacobian = sqrt(rho[1]) * jacobian - + // sqrt(rho[1]) * alpha / sq_norm * residuals residuals' * jacobian. + // + // The method assumes that the jacobian has row-major storage. It is + // the caller's responsibility to ensure that the pointer to + // jacobian is not null. + void CorrectJacobian(int nrow, int ncol, + double* residuals, double* jacobian); + + private: + double sqrt_rho1_; + double residual_scaling_; + double alpha_sq_norm_; +}; +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CORRECTOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h b/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h new file mode 100644 index 00000000000..1177b83a556 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h @@ -0,0 +1,110 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A jacobian writer that writes to dense Eigen matrices. + +#ifndef CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_ +#define CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_ + +#include "ceres/casts.h" +#include "ceres/dense_sparse_matrix.h" +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/scratch_evaluate_preparer.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +class DenseJacobianWriter { + public: + DenseJacobianWriter(Evaluator::Options /* ignored */, + Program* program) + : program_(program) { + } + + // JacobianWriter interface. + + // Since the dense matrix has different layout than that assumed by the cost + // functions, use scratch space to store the jacobians temporarily then copy + // them over to the larger jacobian later. + ScratchEvaluatePreparer* CreateEvaluatePreparers(int num_threads) { + return ScratchEvaluatePreparer::Create(*program_, num_threads); + } + + SparseMatrix* CreateJacobian() const { + return new DenseSparseMatrix(program_->NumResiduals(), + program_->NumEffectiveParameters()); + } + + void Write(int residual_id, + int residual_offset, + double **jacobians, + SparseMatrix* jacobian) { + DenseSparseMatrix* dense_jacobian; + if (jacobian != NULL) { + dense_jacobian = down_cast(jacobian); + } + const ResidualBlock* residual_block = + program_->residual_blocks()[residual_id]; + int num_parameter_blocks = residual_block->NumParameterBlocks(); + int num_residuals = residual_block->NumResiduals(); + + // Now copy the jacobians for each parameter into the dense jacobian matrix. + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + + // If the parameter block is fixed, then there is nothing to do. + if (parameter_block->IsConstant()) { + continue; + } + + int parameter_block_size = parameter_block->LocalSize(); + MatrixRef parameter_jacobian(jacobians[j], + num_residuals, + parameter_block_size); + + dense_jacobian->mutable_matrix().block( + residual_offset, + parameter_block->delta_offset(), + num_residuals, + parameter_block_size) = parameter_jacobian; + } + } + + private: + Program* program_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc new file mode 100644 index 00000000000..328505404d7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc @@ -0,0 +1,93 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/dense_qr_solver.h" + +#include + +#include "Eigen/Dense" +#include "ceres/linear_solver.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +DenseQRSolver::DenseQRSolver(const LinearSolver::Options& options) + : options_(options) {} + +LinearSolver::Summary DenseQRSolver::SolveImpl( + DenseSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + const int num_rows = A->num_rows(); + const int num_cols = A->num_cols(); + VLOG(2) << "DenseQRSolver: " + << num_rows << " x " << num_cols << " system."; + + if (per_solve_options.D != NULL) { + // Temporarily append a diagonal block to the A matrix, but undo + // it before returning the matrix to the user. + A->AppendDiagonal(per_solve_options.D); + } + + // rhs = [b;0] to account for the additional rows in the lhs. + Vector rhs(num_rows + ((per_solve_options.D !=NULL) ? num_cols : 0)); + rhs.setZero(); + rhs.head(num_rows) = ConstVectorRef(b, num_rows); + + // Solve the system. + VectorRef(x, num_cols) = A->matrix().colPivHouseholderQr().solve(rhs); + + VLOG(3) << "A:\n" << A->matrix(); + VLOG(3) << "x:\n" << VectorRef(x, num_cols); + VLOG(3) << "b:\n" << rhs; + VLOG(3) << "error: " << (A->matrix() * VectorRef(x, num_cols) - rhs).norm(); + + + if (per_solve_options.D != NULL) { + // Undo the modifications to the matrix A. + A->RemoveDiagonal(); + } + + // We always succeed, since the QR solver returns the best solution + // it can. It is the job of the caller to determine if the solution + // is good enough or not. + LinearSolver::Summary summary; + summary.num_iterations = 1; + summary.termination_type = TOLERANCE; + return summary; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h new file mode 100644 index 00000000000..990c8d445eb --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h @@ -0,0 +1,99 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Solve dense rectangular systems Ax = b using the QR factoriztion. +#ifndef CERES_INTERNAL_DENSE_QR_SOLVER_H_ +#define CERES_INTERNAL_DENSE_QR_SOLVER_H_ + +#include "ceres/linear_solver.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +class DenseSparseMatrix; + +// This class implements the LinearSolver interface for solving +// rectangular/unsymmetric (well constrained) linear systems of the +// form +// +// Ax = b +// +// Since there does not usually exist a solution that satisfies these +// equations, the solver instead solves the linear least squares +// problem +// +// min_x |Ax - b|^2 +// +// The solution strategy is based on computing the QR decomposition of +// A, i.e. +// +// A = QR +// +// Where Q is an orthonormal matrix and R is an upper triangular +// matrix. Then +// +// Ax = b +// QRx = b +// Q'QRx = Q'b +// Rx = Q'b +// x = R^{-1} Q'b +// +// If the PerSolveOptions struct has a non-null array D, then the +// augmented/regularized linear system +// +// [ A ]x = [b] +// [ diag(D) ] [0] +// +// is solved. +// +// This class uses the dense QR factorization routines from the Eigen +// library. This solver always returns a solution, it is the user's +// responsibility to judge if the solution is good enough for their +// purposes. +class DenseQRSolver: public DenseSparseMatrixSolver { + public: + explicit DenseQRSolver(const LinearSolver::Options& options); + + private: + virtual LinearSolver::Summary SolveImpl( + DenseSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x); + + const LinearSolver::Options options_; + DISALLOW_COPY_AND_ASSIGN(DenseQRSolver); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DENSE_QR_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc new file mode 100644 index 00000000000..ffbfab61de1 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc @@ -0,0 +1,184 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/dense_sparse_matrix.h" + +#include +#include "ceres/matrix_proto.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +DenseSparseMatrix::DenseSparseMatrix(int num_rows, int num_cols) + : has_diagonal_appended_(false), + has_diagonal_reserved_(false) { + // Allocate enough space for the diagonal. + m_.resize(num_rows, num_cols); + m_.setZero(); +} + +DenseSparseMatrix::DenseSparseMatrix(const TripletSparseMatrix& m) + : m_(Eigen::MatrixXd::Zero(m.num_rows(), m.num_cols())), + has_diagonal_appended_(false), + has_diagonal_reserved_(false) { + const double *values = m.values(); + const int *rows = m.rows(); + const int *cols = m.cols(); + int num_nonzeros = m.num_nonzeros(); + + for (int i = 0; i < num_nonzeros; ++i) { + m_(rows[i], cols[i]) += values[i]; + } +} + +DenseSparseMatrix::DenseSparseMatrix(const Matrix& m) + : m_(m), + has_diagonal_appended_(false), + has_diagonal_reserved_(false) { +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +DenseSparseMatrix::DenseSparseMatrix(const SparseMatrixProto& outer_proto) + : m_(Eigen::MatrixXd::Zero( + outer_proto.dense_matrix().num_rows(), + outer_proto.dense_matrix().num_cols())), + has_diagonal_appended_(false), + has_diagonal_reserved_(false) { + const DenseSparseMatrixProto& proto = outer_proto.dense_matrix(); + for (int i = 0; i < m_.rows(); ++i) { + for (int j = 0; j < m_.cols(); ++j) { + m_(i, j) = proto.values(m_.cols() * i + j); + } + } +} +#endif + +void DenseSparseMatrix::SetZero() { + m_.setZero(); +} + +void DenseSparseMatrix::RightMultiply(const double* x, double* y) const { + VectorRef(y, num_rows()) += matrix() * ConstVectorRef(x, num_cols()); +} + +void DenseSparseMatrix::LeftMultiply(const double* x, double* y) const { + VectorRef(y, num_cols()) += + matrix().transpose() * ConstVectorRef(x, num_rows()); +} + +void DenseSparseMatrix::SquaredColumnNorm(double* x) const { + VectorRef(x, num_cols()) = m_.colwise().squaredNorm(); +} + +void DenseSparseMatrix::ScaleColumns(const double* scale) { + m_ *= ConstVectorRef(scale, num_cols()).asDiagonal(); +} + +void DenseSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { + *dense_matrix = m_; +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void DenseSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { + CHECK(!has_diagonal_appended_) << "Not supported."; + outer_proto->Clear(); + DenseSparseMatrixProto* proto = outer_proto->mutable_dense_matrix(); + + proto->set_num_rows(num_rows()); + proto->set_num_cols(num_cols()); + + int num_nnz = num_nonzeros(); + for (int i = 0; i < num_nnz; ++i) { + proto->add_values(m_.data()[i]); + } +} +#endif + +void DenseSparseMatrix::AppendDiagonal(double *d) { + CHECK(!has_diagonal_appended_); + if (!has_diagonal_reserved_) { + Matrix tmp = m_; + m_.resize(m_.rows() + m_.cols(), m_.cols()); + m_.setZero(); + m_.block(0, 0, tmp.rows(), tmp.cols()) = tmp; + has_diagonal_reserved_ = true; + } + + m_.bottomLeftCorner(m_.cols(), m_.cols()) = + ConstVectorRef(d, m_.cols()).asDiagonal(); + has_diagonal_appended_ = true; +} + +void DenseSparseMatrix::RemoveDiagonal() { + CHECK(has_diagonal_appended_); + has_diagonal_appended_ = false; + // Leave the diagonal reserved. +} + +int DenseSparseMatrix::num_rows() const { + if (has_diagonal_reserved_ && !has_diagonal_appended_) { + return m_.rows() - m_.cols(); + } + return m_.rows(); +} + +int DenseSparseMatrix::num_cols() const { + return m_.cols(); +} + +int DenseSparseMatrix::num_nonzeros() const { + if (has_diagonal_reserved_ && !has_diagonal_appended_) { + return (m_.rows() - m_.cols()) * m_.cols(); + } + return m_.rows() * m_.cols(); +} + +ConstAlignedMatrixRef DenseSparseMatrix::matrix() const { + if (has_diagonal_reserved_ && !has_diagonal_appended_) { + return ConstAlignedMatrixRef( + m_.data(), m_.rows() - m_.cols(), m_.cols()); + } + return ConstAlignedMatrixRef(m_.data(), m_.rows(), m_.cols()); +} + +AlignedMatrixRef DenseSparseMatrix::mutable_matrix() { + if (has_diagonal_reserved_ && !has_diagonal_appended_) { + return AlignedMatrixRef( + m_.data(), m_.rows() - m_.cols(), m_.cols()); + } + return AlignedMatrixRef(m_.data(), m_.rows(), m_.cols()); +} + + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h new file mode 100644 index 00000000000..5ce29eef51b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h @@ -0,0 +1,115 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A dense matrix implemented under the SparseMatrix interface. + +#ifndef CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_ + +#include +#include "ceres/sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; +class TripletSparseMatrix; + +class DenseSparseMatrix : public SparseMatrix { + public: + // Build a matrix with the same content as the TripletSparseMatrix + // m. This assumes that m does not have any repeated entries. + explicit DenseSparseMatrix(const TripletSparseMatrix& m); + explicit DenseSparseMatrix(const Matrix& m); +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + explicit DenseSparseMatrix(const SparseMatrixProto& proto); +#endif + + DenseSparseMatrix(int num_rows, int num_cols); + + virtual ~DenseSparseMatrix() {} + + // SparseMatrix interface. + virtual void SetZero(); + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual void SquaredColumnNorm(double* x) const; + virtual void ScaleColumns(const double* scale); + virtual void ToDenseMatrix(Matrix* dense_matrix) const; +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + virtual void ToProto(SparseMatrixProto* proto) const; +#endif + virtual int num_rows() const; + virtual int num_cols() const; + virtual int num_nonzeros() const; + virtual const double* values() const { return m_.data(); } + virtual double* mutable_values() { return m_.data(); } + + ConstAlignedMatrixRef matrix() const; + AlignedMatrixRef mutable_matrix(); + + // Only one diagonal can be appended at a time. The diagonal is appended to + // as a new set of rows, e.g. + // + // Original matrix: + // + // x x x + // x x x + // x x x + // + // After append diagonal (1, 2, 3): + // + // x x x + // x x x + // x x x + // 1 0 0 + // 0 2 0 + // 0 0 3 + // + // Calling RemoveDiagonal removes the block. It is a fatal error to append a + // diagonal to a matrix that already has an appended diagonal, and it is also + // a fatal error to remove a diagonal from a matrix that has none. + void AppendDiagonal(double *d); + void RemoveDiagonal(); + + private: + Matrix m_; + bool has_diagonal_appended_; + bool has_diagonal_reserved_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc new file mode 100644 index 00000000000..e9755043bab --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc @@ -0,0 +1,114 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include +#include "ceres/detect_structure.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +void DetectStructure(const CompressedRowBlockStructure& bs, + const int num_eliminate_blocks, + int* row_block_size, + int* e_block_size, + int* f_block_size) { + const int num_row_blocks = bs.rows.size(); + *row_block_size = 0; + *e_block_size = 0; + *f_block_size = 0; + + // Iterate over row blocks of the matrix, checking if row_block, + // e_block or f_block sizes remain constant. + for (int r = 0; r < num_row_blocks; ++r) { + const CompressedRow& row = bs.rows[r]; + // We do not care about the sizes of the blocks in rows which do + // not contain e_blocks. + if (row.cells.front().block_id >= num_eliminate_blocks) { + break; + } + const int e_block_id = row.cells.front().block_id; + + if (*row_block_size == 0) { + *row_block_size = row.block.size; + } else if (*row_block_size != Eigen::Dynamic && + *row_block_size != row.block.size) { + *row_block_size = Eigen::Dynamic; + VLOG(2) << "Dynamic row block size because the block size changed from " + << *row_block_size << " to " + << row.block.size; + } + + + if (*e_block_size == 0) { + *e_block_size = bs.cols[e_block_id].size; + } else if (*e_block_size != Eigen::Dynamic && + *e_block_size != bs.cols[e_block_id].size) { + *e_block_size = Eigen::Dynamic; + VLOG(2) << "Dynamic e block size because the block size changed from " + << *e_block_size << " to " + << bs.cols[e_block_id].size; + } + + if (*f_block_size == 0) { + if (row.cells.size() > 1) { + const int f_block_id = row.cells[1].block_id; + *f_block_size = bs.cols[f_block_id].size; + } + } else if (*f_block_size != Eigen::Dynamic) { + for (int c = 1; c < row.cells.size(); ++c) { + if (*f_block_size != bs.cols[row.cells[c].block_id].size) { + *f_block_size = Eigen::Dynamic; + VLOG(2) << "Dynamic f block size because the block size " + << "changed from " << *f_block_size << " to " + << bs.cols[row.cells[c].block_id].size; + break; + } + } + } + + const bool is_everything_dynamic = (*row_block_size == Eigen::Dynamic && + *e_block_size == Eigen::Dynamic && + *f_block_size == Eigen::Dynamic); + if (is_everything_dynamic) { + break; + } + } + + CHECK_NE(*row_block_size, 0) << "No rows found"; + CHECK_NE(*e_block_size, 0) << "No e type blocks found"; + VLOG(1) << "Schur complement static structure <" + << *row_block_size << "," + << *e_block_size << "," + << *f_block_size << ">."; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h new file mode 100644 index 00000000000..8af4f236690 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h @@ -0,0 +1,63 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_DETECT_STRUCTURE_H_ +#define CERES_INTERNAL_DETECT_STRUCTURE_H_ + +#include "ceres/block_structure.h" + +namespace ceres { +namespace internal { + +// Detect static blocks in the problem sparsity. For rows containing +// e_blocks, we are interested in detecting if the size of the row +// blocks, e_blocks and the f_blocks remain constant. If they do, then +// we can use template specialization to improve the performance of +// the block level linear algebra operations used by the +// SchurEliminator. +// +// If a block size is not constant, we return Eigen::Dynamic as the +// value. This just means that the eliminator uses dynamically sized +// linear algebra operations rather than static operations whose size +// is known as compile time. +// +// For more details about e_blocks and f_blocks, see +// schur_complement.h. This information is used to initialized an +// appropriate template specialization of SchurEliminator. +void DetectStructure(const CompressedRowBlockStructure& bs, + const int num_eliminate_blocks, + int* row_block_size, + int* e_block_size, + int* f_block_size); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DETECT_STRUCTURE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc new file mode 100644 index 00000000000..ea05aefec8c --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc @@ -0,0 +1,71 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include +#include "ceres/evaluator.h" +#include "ceres/block_evaluate_preparer.h" +#include "ceres/block_jacobian_writer.h" +#include "ceres/compressed_row_jacobian_writer.h" +#include "ceres/scratch_evaluate_preparer.h" +#include "ceres/dense_jacobian_writer.h" +#include "ceres/program_evaluator.h" + +namespace ceres { +namespace internal { + +Evaluator::~Evaluator() {} + +Evaluator* Evaluator::Create(const Evaluator::Options& options, + Program* program, + string* error) { + switch (options.linear_solver_type) { + case DENSE_QR: + return new ProgramEvaluator(options, + program); + case DENSE_SCHUR: + case SPARSE_SCHUR: + case ITERATIVE_SCHUR: + case CGNR: + return new ProgramEvaluator(options, + program); + case SPARSE_NORMAL_CHOLESKY: + return new ProgramEvaluator(options, + program); + default: + *error = "Invalid Linear Solver Type. Unable to create evaluator."; + return NULL; + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h new file mode 100644 index 00000000000..adefdd26660 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h @@ -0,0 +1,129 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_EVALUATOR_H_ +#define CERES_INTERNAL_EVALUATOR_H_ + +#include +#include "ceres/internal/port.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class Program; +class SparseMatrix; + +// The Evaluator interface offers a way to interact with a least squares cost +// function that is useful for an optimizer that wants to minimize the least +// squares objective. This insulates the optimizer from issues like Jacobian +// storage, parameterization, etc. +class Evaluator { + public: + virtual ~Evaluator(); + + struct Options { + Options() + : num_threads(1), + num_eliminate_blocks(-1), + linear_solver_type(DENSE_QR) {} + + int num_threads; + int num_eliminate_blocks; + LinearSolverType linear_solver_type; + }; + + static Evaluator* Create(const Options& options, + Program* program, + string* error); + + // Build and return a sparse matrix for storing and working with the Jacobian + // of the objective function. The jacobian has dimensions + // NumEffectiveParameters() by NumParameters(), and is typically extremely + // sparse. Since the sparsity pattern of the Jacobian remains constant over + // the lifetime of the optimization problem, this method is used to + // instantiate a SparseMatrix object with the appropriate sparsity structure + // (which can be an expensive operation) and then reused by the optimization + // algorithm and the various linear solvers. + // + // It is expected that the classes implementing this interface will be aware + // of their client's requirements for the kind of sparse matrix storage and + // layout that is needed for an efficient implementation. For example + // CompressedRowOptimizationProblem creates a compressed row representation of + // the jacobian for use with CHOLMOD, where as BlockOptimizationProblem + // creates a BlockSparseMatrix representation of the jacobian for use in the + // Schur complement based methods. + virtual SparseMatrix* CreateJacobian() const = 0; + + // Evaluate the cost function for the given state. Returns the cost, + // residuals, and jacobian in the corresponding arguments. Both residuals and + // jacobian are optional; to avoid computing them, pass NULL. + // + // If non-NULL, the Jacobian must have a suitable sparsity pattern; only the + // values array of the jacobian is modified. + // + // state is an array of size NumParameters(), cost is a pointer to a single + // double, and residuals is an array of doubles of size NumResiduals(). + virtual bool Evaluate(const double* state, + double* cost, + double* residuals, + SparseMatrix* jacobian) = 0; + + // Make a change delta (of size NumEffectiveParameters()) to state (of size + // NumParameters()) and store the result in state_plus_delta. + // + // In the case that there are no parameterizations used, this is equivalent to + // + // state_plus_delta[i] = state[i] + delta[i] ; + // + // however, the mapping is more complicated in the case of parameterizations + // like quaternions. This is the same as the "Plus()" operation in + // local_parameterization.h, but operating over the entire state vector for a + // problem. + virtual bool Plus(const double* state, + const double* delta, + double* state_plus_delta) const = 0; + + // The number of parameters in the optimization problem. + virtual int NumParameters() const = 0; + + // This is the effective number of parameters that the optimizer may adjust. + // This applies when there are parameterizations on some of the parameters. + virtual int NumEffectiveParameters() const = 0; + + // The number of residuals in the optimization problem. + virtual int NumResiduals() const = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_EVALUATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/file.cc b/extern/libmv/third_party/ceres/internal/ceres/file.cc new file mode 100644 index 00000000000..5fc9d220861 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/file.cc @@ -0,0 +1,93 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Really simple file IO. + +#include +#include + +namespace ceres { +namespace internal { + +using std::string; + +void WriteStringToFileOrDie(const string &data, const string &filename) { + FILE* file_descriptor = fopen(filename.c_str(), "wb"); + if (!file_descriptor) { + LOG(FATAL) << "Couldn't write to file: " << filename; + } + fwrite(data.c_str(), 1, data.size(), file_descriptor); + fclose(file_descriptor); +} + +void ReadFileToStringOrDie(const string &filename, string *data) { + FILE* file_descriptor = file_descriptor = fopen(filename.c_str(), "r"); + + if (!file_descriptor) { + LOG(FATAL) << "Couldn't read file: " << filename; + } + + // Resize the input buffer appropriately. + fseek(file_descriptor, 0L, SEEK_END); + int num_bytes = ftell(file_descriptor); + data->resize(num_bytes); + + // Read the data. + fseek(file_descriptor, 0L, SEEK_SET); + int num_read = fread(&((*data)[0]), + sizeof((*data)[0]), + num_bytes, + file_descriptor); + if (num_read != num_bytes) { + LOG(FATAL) << "Couldn't read all of " << filename + << "expected bytes: " << num_bytes * sizeof((*data)[0]) + << "actual bytes: " << num_read; + } + fclose(file_descriptor); +} + +string JoinPath(const string& dirname, const string& basename) { +#ifdef _WIN32 + static const char separator = '\\'; +#else + static const char separator = '/'; +#endif // _WIN32 + + if ((!basename.empty() && basename[0] == separator) || dirname.empty()) { + return basename; + } else if (dirname[dirname.size() - 1] == separator) { + return dirname + basename; + } else { + return dirname + string(&separator, 1) + basename; + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/file.h b/extern/libmv/third_party/ceres/internal/ceres/file.h new file mode 100644 index 00000000000..4741d650646 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/file.h @@ -0,0 +1,52 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Simple file IO support. This is a portability shim. + +#ifndef CERES_INTERNAL_FILE_H_ +#define CERES_INTERNAL_FILE_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +void WriteStringToFileOrDie(const string &data, const string &filename); +void ReadFileToStringOrDie(const string &filename, string *data); + +// Join two path components, adding a slash if necessary. If basename is an +// absolute path then JoinPath ignores dirname and simply returns basename. +string JoinPath(const string& dirname, const string& basename); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_FILE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc new file mode 100644 index 00000000000..5529386e485 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 2, 2>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc new file mode 100644 index 00000000000..fd7af95192e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 2, 3>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc new file mode 100644 index 00000000000..109483e9fc0 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 2, 4>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc new file mode 100644 index 00000000000..b93e82fe2fa --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 2, Dynamic>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc new file mode 100644 index 00000000000..86352c07304 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 3, 3>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc new file mode 100644 index 00000000000..200df7f5931 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 3, 4>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc new file mode 100644 index 00000000000..1fda3434bef --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 3, 9>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc new file mode 100644 index 00000000000..385cd2d70c9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 3, Dynamic>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc new file mode 100644 index 00000000000..7b15d6366ac --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 4, 3>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc new file mode 100644 index 00000000000..29a610d743e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 4, 4>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc new file mode 100644 index 00000000000..a3bc4dc6f83 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 4, Dynamic>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc new file mode 100644 index 00000000000..f71a4f62944 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<4, 4, 2>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc new file mode 100644 index 00000000000..52259fb1a67 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<4, 4, 3>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc new file mode 100644 index 00000000000..775424e6c8f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<4, 4, 4>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc new file mode 100644 index 00000000000..97cde594059 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<4, 4, Dynamic>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc new file mode 100644 index 00000000000..4cba32e26c8 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc new file mode 100644 index 00000000000..abba40824ef --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc @@ -0,0 +1,308 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/gradient_checking_cost_function.h" + +#include +#include +#include +#include +#include + +#include +#include "ceres/parameter_block.h" +#include "ceres/problem_impl.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/runtime_numeric_diff_cost_function.h" +#include "ceres/stringprintf.h" +#include "ceres/cost_function.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/problem.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { +namespace { + +// True if x and y have an absolute relative difference less than +// relative_precision and false otherwise. Stores the relative and absolute +// difference in relative/absolute_error if non-NULL. +bool IsClose(double x, double y, double relative_precision, + double *relative_error, + double *absolute_error) { + double local_absolute_error; + double local_relative_error; + if (!absolute_error) { + absolute_error = &local_absolute_error; + } + if (!relative_error) { + relative_error = &local_relative_error; + } + *absolute_error = fabs(x - y); + *relative_error = *absolute_error / max(fabs(x), fabs(y)); + if (x == 0 || y == 0) { + // If x or y is exactly zero, then relative difference doesn't have any + // meaning. Take the absolute difference instead. + *relative_error = *absolute_error; + } + return fabs(*relative_error) < fabs(relative_precision); +} + +class GradientCheckingCostFunction : public CostFunction { + public: + GradientCheckingCostFunction(const CostFunction* function, + double relative_step_size, + double relative_precision, + const string& extra_info) + : function_(function), + finite_diff_cost_function_( + CreateRuntimeNumericDiffCostFunction(function, + CENTRAL, + relative_step_size)), + relative_precision_(relative_precision), + extra_info_(extra_info) { + *mutable_parameter_block_sizes() = function->parameter_block_sizes(); + set_num_residuals(function->num_residuals()); + } + + virtual ~GradientCheckingCostFunction() { } + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + if (!jacobians) { + // Nothing to check in this case; just forward. + return function_->Evaluate(parameters, residuals, NULL); + } + + int num_residuals = function_->num_residuals(); + + // Make space for the jacobians of the two methods. + const vector& block_sizes = function_->parameter_block_sizes(); + vector term_jacobians(block_sizes.size()); + vector finite_difference_jacobians(block_sizes.size()); + vector term_jacobian_pointers(block_sizes.size()); + vector finite_difference_jacobian_pointers(block_sizes.size()); + for (int i = 0; i < block_sizes.size(); i++) { + term_jacobians[i].resize(num_residuals, block_sizes[i]); + term_jacobian_pointers[i] = term_jacobians[i].data(); + finite_difference_jacobians[i].resize(num_residuals, block_sizes[i]); + finite_difference_jacobian_pointers[i] = + finite_difference_jacobians[i].data(); + } + + // Evaluate the derivative using the user supplied code. + if (!function_->Evaluate(parameters, + residuals, + &term_jacobian_pointers[0])) { + LOG(WARNING) << "Function evaluation failed."; + return false; + } + + // Evaluate the derivative using numeric derivatives. + finite_diff_cost_function_->Evaluate( + parameters, + residuals, + &finite_difference_jacobian_pointers[0]); + + // See if any elements have relative error larger than the threshold. + int num_bad_jacobian_components = 0; + double worst_relative_error = 0; + + // Accumulate the error message for all the jacobians, since it won't get + // output if there are no bad jacobian components. + string m; + for (int k = 0; k < block_sizes.size(); k++) { + // Copy the original jacobian blocks into the jacobians array. + if (jacobians[k] != NULL) { + MatrixRef(jacobians[k], + term_jacobians[k].rows(), + term_jacobians[k].cols()) = term_jacobians[k]; + } + + StringAppendF(&m, + "========== " + "Jacobian for " "block %d: (%ld by %ld)) " + "==========\n", + k, + term_jacobians[k].rows(), + term_jacobians[k].cols()); + // The funny spacing creates appropriately aligned column headers. + m += " block row col user dx/dy num diff dx/dy " + "abs error relative error parameter residual\n"; + + for (int i = 0; i < term_jacobians[k].rows(); i++) { + for (int j = 0; j < term_jacobians[k].cols(); j++) { + double term_jacobian = term_jacobians[k](i, j); + double finite_jacobian = finite_difference_jacobians[k](i, j); + double relative_error, absolute_error; + bool bad_jacobian_entry = + !IsClose(term_jacobian, + finite_jacobian, + relative_precision_, + &relative_error, + &absolute_error); + worst_relative_error = std::max(worst_relative_error, + relative_error); + + StringAppendF(&m, "%6d %4d %4d %17g %17g %17g %17g %17g %17g", + k, i, j, + term_jacobian, finite_jacobian, + absolute_error, relative_error, + parameters[k][j], + residuals[i]); + + if (bad_jacobian_entry) { + num_bad_jacobian_components++; + StringAppendF( + &m, " ------ (%d,%d,%d) Relative error worse than %g", + k, i, j, relative_precision_); + } + m += "\n"; + } + } + } + + // Since there were some bad errors, dump comprehensive debug info. + if (num_bad_jacobian_components) { + string header = StringPrintf("Detected %d bad jacobian component(s). " + "Worst relative error was %g.\n", + num_bad_jacobian_components, + worst_relative_error); + if (!extra_info_.empty()) { + header += "Extra info for this residual: " + extra_info_ + "\n"; + } + LOG(WARNING) << "\n" << header << m; + } + return true; + } + + private: + const CostFunction* function_; + internal::scoped_ptr finite_diff_cost_function_; + double relative_precision_; + string extra_info_; +}; + +} // namespace + +CostFunction *CreateGradientCheckingCostFunction( + const CostFunction *cost_function, + double relative_step_size, + double relative_precision, + const string& extra_info) { + return new GradientCheckingCostFunction(cost_function, + relative_step_size, + relative_precision, + extra_info); +} + +ProblemImpl* CreateGradientCheckingProblemImpl(ProblemImpl* problem_impl, + double relative_step_size, + double relative_precision) { + // We create new CostFunctions by wrapping the original CostFunction + // in a gradient checking CostFunction. So its okay for the + // ProblemImpl to take ownership of it and destroy it. The + // LossFunctions and LocalParameterizations are reused and since + // they are owned by problem_impl, gradient_checking_problem_impl + // should not take ownership of it. + Problem::Options gradient_checking_problem_options; + gradient_checking_problem_options.cost_function_ownership = TAKE_OWNERSHIP; + gradient_checking_problem_options.loss_function_ownership = + DO_NOT_TAKE_OWNERSHIP; + gradient_checking_problem_options.local_parameterization_ownership = + DO_NOT_TAKE_OWNERSHIP; + + ProblemImpl* gradient_checking_problem_impl = new ProblemImpl( + gradient_checking_problem_options); + + Program* program = problem_impl->mutable_program(); + + // For every ParameterBlock in problem_impl, create a new parameter + // block with the same local parameterization and constancy. + const vector& parameter_blocks = program->parameter_blocks(); + for (int i = 0; i < parameter_blocks.size(); ++i) { + ParameterBlock* parameter_block = parameter_blocks[i]; + gradient_checking_problem_impl->AddParameterBlock( + parameter_block->mutable_user_state(), + parameter_block->Size(), + parameter_block->mutable_local_parameterization()); + + if (parameter_block->IsConstant()) { + gradient_checking_problem_impl->SetParameterBlockConstant( + parameter_block->mutable_user_state()); + } + } + + // For every ResidualBlock in problem_impl, create a new + // ResidualBlock by wrapping its CostFunction inside a + // GradientCheckingCostFunction. + const vector& residual_blocks = program->residual_blocks(); + for (int i = 0; i < residual_blocks.size(); ++i) { + ResidualBlock* residual_block = residual_blocks[i]; + + // Build a human readable string which identifies the + // ResidualBlock. This is used by the GradientCheckingCostFunction + // when logging debugging information. + string extra_info = StringPrintf( + "Residual block id %d; depends on parameters [", i); + vector parameter_blocks; + for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + parameter_blocks.push_back(parameter_block->mutable_user_state()); + StringAppendF(&extra_info, "%p", parameter_block->mutable_user_state()); + extra_info += (j < residual_block->NumParameterBlocks() - 1) ? ", " : "]"; + } + + // Wrap the original CostFunction in a GradientCheckingCostFunction. + CostFunction* gradient_checking_cost_function = + CreateGradientCheckingCostFunction(residual_block->cost_function(), + relative_step_size, + relative_precision, + extra_info); + + // The const_cast is necessary because + // ProblemImpl::AddResidualBlock can potentially take ownership of + // the LossFunction, but in this case we are guaranteed that this + // will not be the case, so this const_cast is harmless. + gradient_checking_problem_impl->AddResidualBlock( + gradient_checking_cost_function, + const_cast(residual_block->loss_function()), + parameter_blocks); + } + + return gradient_checking_problem_impl; +} + + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.h b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.h new file mode 100644 index 00000000000..d49c8e6c244 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.h @@ -0,0 +1,85 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_ +#define CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_ + +#include + +#include "ceres/cost_function.h" + +namespace ceres { +namespace internal { + +class ProblemImpl; + +// Creates a CostFunction that checks the jacobians that cost_function computes +// with finite differences. Bad results are logged; required precision is +// controlled by relative_precision and the numeric differentiation step size is +// controlled with relative_step_size. See solver.h for a better explanation of +// relative_step_size. Caller owns result. +// +// The condition enforced is that +// +// (J_actual(i, j) - J_numeric(i, j)) +// ------------------------------------ < relative_precision +// max(J_actual(i, j), J_numeric(i, j)) +// +// where J_actual(i, j) is the jacobian as computed by the supplied cost +// function (by the user) and J_numeric is the jacobian as computed by finite +// differences. +// +// Note: This is quite inefficient and is intended only for debugging. +CostFunction* CreateGradientCheckingCostFunction( + const CostFunction* cost_function, + double relative_step_size, + double relative_precision, + const string& extra_info); + +// Create a new ProblemImpl object from the input problem_impl, where +// each CostFunctions in problem_impl are wrapped inside a +// GradientCheckingCostFunctions. This gives us a ProblemImpl object +// which checks its derivatives against estimates from numeric +// differentiation everytime a ResidualBlock is evaluated. +// +// relative_step_size and relative_precision are parameters to control +// the numeric differentiation and the relative tolerance between the +// jacobian computed by the CostFunctions in problem_impl and +// jacobians obtained by numerically differentiating them. For more +// details see the documentation for +// CreateGradientCheckingCostFunction above. +ProblemImpl* CreateGradientCheckingProblemImpl(ProblemImpl* problem_impl, + double relative_step_size, + double relative_precision); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph.h b/extern/libmv/third_party/ceres/internal/ceres/graph.h new file mode 100644 index 00000000000..fd7a224f0aa --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/graph.h @@ -0,0 +1,138 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_GRAPH_H_ +#define CERES_INTERNAL_GRAPH_H_ + +#include +#include +#include "ceres/integral_types.h" +#include "ceres/map_util.h" +#include "ceres/collections_port.h" +#include "ceres/internal/macros.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +// A weighted undirected graph templated over the vertex ids. Vertex +// should be hashable and comparable. +template +class Graph { + public: + Graph() {} + + // Add a weighted vertex. If the vertex already exists in the graph, + // its weight is set to the new weight. + void AddVertex(const Vertex& vertex, double weight) { + if (vertices_.find(vertex) == vertices_.end()) { + vertices_.insert(vertex); + edges_[vertex] = HashSet(); + } + vertex_weights_[vertex] = weight; + } + + // Uses weight = 1.0. If vertex already exists, its weight is set to + // 1.0. + void AddVertex(const Vertex& vertex) { + AddVertex(vertex, 1.0); + } + + // Add a weighted edge between the vertex1 and vertex2. Calling + // AddEdge on a pair of vertices which do not exist in the graph yet + // will result in undefined behavior. + // + // It is legal to call this method repeatedly for the same set of + // vertices. + void AddEdge(const Vertex& vertex1, const Vertex& vertex2, double weight) { + DCHECK(vertices_.find(vertex1) != vertices_.end()); + DCHECK(vertices_.find(vertex2) != vertices_.end()); + + if (edges_[vertex1].insert(vertex2).second) { + edges_[vertex2].insert(vertex1); + } + + if (vertex1 < vertex2) { + edge_weights_[make_pair(vertex1, vertex2)] = weight; + } else { + edge_weights_[make_pair(vertex2, vertex1)] = weight; + } + } + + // Uses weight = 1.0. + void AddEdge(const Vertex& vertex1, const Vertex& vertex2) { + AddEdge(vertex1, vertex2, 1.0); + } + + // Calling VertexWeight on a vertex not in the graph will result in + // undefined behavior. + double VertexWeight(const Vertex& vertex) const { + return FindOrDie(vertex_weights_, vertex); + } + + // Calling EdgeWeight on a pair of vertices where either one of the + // vertices is not present in the graph will result in undefined + // behaviour. If there is no edge connecting vertex1 and vertex2, + // the edge weight is zero. + double EdgeWeight(const Vertex& vertex1, const Vertex& vertex2) const { + if (vertex1 < vertex2) { + return FindWithDefault(edge_weights_, make_pair(vertex1, vertex2), 0.0); + } else { + return FindWithDefault(edge_weights_, make_pair(vertex2, vertex1), 0.0); + } + } + + // Calling Neighbors on a vertex not in the graph will result in + // undefined behaviour. + const HashSet& Neighbors(const Vertex& vertex) const { + return FindOrDie(edges_, vertex); + } + + const HashSet& vertices() const { + return vertices_; + } + + static double InvalidWeight() { + return std::numeric_limits::quiet_NaN(); + }; + + private: + HashSet vertices_; + HashMap vertex_weights_; + HashMap > edges_; + HashMap, double> edge_weights_; + + DISALLOW_COPY_AND_ASSIGN(Graph); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_GRAPH_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h b/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h new file mode 100644 index 00000000000..3b42d936336 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h @@ -0,0 +1,270 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Various algorithms that operate on undirected graphs. + +#ifndef CERES_INTERNAL_GRAPH_ALGORITHMS_H_ +#define CERES_INTERNAL_GRAPH_ALGORITHMS_H_ + +#include +#include +#include "ceres/collections_port.h" +#include "ceres/graph.h" + +namespace ceres { +namespace internal { + +// Compare two vertices of a graph by their degrees. +template +class VertexDegreeLessThan { + public: + explicit VertexDegreeLessThan(const Graph& graph) + : graph_(graph) {} + + bool operator()(const Vertex& lhs, const Vertex& rhs) const { + if (graph_.Neighbors(lhs).size() == graph_.Neighbors(rhs).size()) { + return lhs < rhs; + } + return graph_.Neighbors(lhs).size() < graph_.Neighbors(rhs).size(); + } + + private: + const Graph& graph_; +}; + +// Order the vertices of a graph using its (approximately) largest +// independent set, where an independent set of a graph is a set of +// vertices that have no edges connecting them. The maximum +// independent set problem is NP-Hard, but there are effective +// approximation algorithms available. The implementation here uses a +// breadth first search that explores the vertices in order of +// increasing degree. The same idea is used by Saad & Li in "MIQR: A +// multilevel incomplete QR preconditioner for large sparse +// least-squares problems", SIMAX, 2007. +// +// Given a undirected graph G(V,E), the algorithm is a greedy BFS +// search where the vertices are explored in increasing order of their +// degree. The output vector ordering contains elements of S in +// increasing order of their degree, followed by elements of V - S in +// increasing order of degree. The return value of the function is the +// cardinality of S. +template +int IndependentSetOrdering(const Graph& graph, + vector* ordering) { + const HashSet& vertices = graph.vertices(); + const int num_vertices = vertices.size(); + + CHECK_NOTNULL(ordering); + ordering->clear(); + ordering->reserve(num_vertices); + + // Colors for labeling the graph during the BFS. + const char kWhite = 0; + const char kGrey = 1; + const char kBlack = 2; + + // Mark all vertices white. + HashMap vertex_color; + vector vertex_queue; + for (typename HashSet::const_iterator it = vertices.begin(); + it != vertices.end(); + ++it) { + vertex_color[*it] = kWhite; + vertex_queue.push_back(*it); + } + + + sort(vertex_queue.begin(), vertex_queue.end(), + VertexDegreeLessThan(graph)); + + // Iterate over vertex_queue. Pick the first white vertex, add it + // to the independent set. Mark it black and its neighbors grey. + for (int i = 0; i < vertex_queue.size(); ++i) { + const Vertex& vertex = vertex_queue[i]; + if (vertex_color[vertex] != kWhite) { + continue; + } + + ordering->push_back(vertex); + vertex_color[vertex] = kBlack; + const HashSet& neighbors = graph.Neighbors(vertex); + for (typename HashSet::const_iterator it = neighbors.begin(); + it != neighbors.end(); + ++it) { + vertex_color[*it] = kGrey; + } + } + + int independent_set_size = ordering->size(); + + // Iterate over the vertices and add all the grey vertices to the + // ordering. At this stage there should only be black or grey + // vertices in the graph. + for (typename vector::const_iterator it = vertex_queue.begin(); + it != vertex_queue.end(); + ++it) { + const Vertex vertex = *it; + DCHECK(vertex_color[vertex] != kWhite); + if (vertex_color[vertex] != kBlack) { + ordering->push_back(vertex); + } + } + + CHECK_EQ(ordering->size(), num_vertices); + return independent_set_size; +} + +// Find the connected component for a vertex implemented using the +// find and update operation for disjoint-set. Recursively traverse +// the disjoint set structure till you reach a vertex whose connected +// component has the same id as the vertex itself. Along the way +// update the connected components of all the vertices. This updating +// is what gives this data structure its efficiency. +template +Vertex FindConnectedComponent(const Vertex& vertex, + HashMap* union_find) { + typename HashMap::iterator it = union_find->find(vertex); + DCHECK(it != union_find->end()); + if (it->second != vertex) { + it->second = FindConnectedComponent(it->second, union_find); + } + + return it->second; +} + +// Compute a degree two constrained Maximum Spanning Tree/forest of +// the input graph. Caller owns the result. +// +// Finding degree 2 spanning tree of a graph is not always +// possible. For example a star graph, i.e. a graph with n-nodes +// where one node is connected to the other n-1 nodes does not have +// a any spanning trees of degree less than n-1.Even if such a tree +// exists, finding such a tree is NP-Hard. + +// We get around both of these problems by using a greedy, degree +// constrained variant of Kruskal's algorithm. We start with a graph +// G_T with the same vertex set V as the input graph G(V,E) but an +// empty edge set. We then iterate over the edges of G in decreasing +// order of weight, adding them to G_T if doing so does not create a +// cycle in G_T} and the degree of all the vertices in G_T remains +// bounded by two. This O(|E|) algorithm results in a degree-2 +// spanning forest, or a collection of linear paths that span the +// graph G. +template +Graph* +Degree2MaximumSpanningForest(const Graph& graph) { + // Array of edges sorted in decreasing order of their weights. + vector > > weighted_edges; + Graph* forest = new Graph(); + + // Disjoint-set to keep track of the connected components in the + // maximum spanning tree. + HashMap disjoint_set; + + // Sort of the edges in the graph in decreasing order of their + // weight. Also add the vertices of the graph to the Maximum + // Spanning Tree graph and set each vertex to be its own connected + // component in the disjoint_set structure. + const HashSet& vertices = graph.vertices(); + for (typename HashSet::const_iterator it = vertices.begin(); + it != vertices.end(); + ++it) { + const Vertex vertex1 = *it; + forest->AddVertex(vertex1, graph.VertexWeight(vertex1)); + disjoint_set[vertex1] = vertex1; + + const HashSet& neighbors = graph.Neighbors(vertex1); + for (typename HashSet::const_iterator it2 = neighbors.begin(); + it2 != neighbors.end(); + ++it2) { + const Vertex vertex2 = *it2; + if (vertex1 >= vertex2) { + continue; + } + const double weight = graph.EdgeWeight(vertex1, vertex2); + weighted_edges.push_back(make_pair(weight, make_pair(vertex1, vertex2))); + } + } + + // The elements of this vector, are pairs. Sorting it using the reverse iterators gives us the edges + // in decreasing order of edges. + sort(weighted_edges.rbegin(), weighted_edges.rend()); + + // Greedily add edges to the spanning tree/forest as long as they do + // not violate the degree/cycle constraint. + for (int i =0; i < weighted_edges.size(); ++i) { + const pair& edge = weighted_edges[i].second; + const Vertex vertex1 = edge.first; + const Vertex vertex2 = edge.second; + + // Check if either of the vertices are of degree 2 already, in + // which case adding this edge will violate the degree 2 + // constraint. + if ((forest->Neighbors(vertex1).size() == 2) || + (forest->Neighbors(vertex2).size() == 2)) { + continue; + } + + // Find the id of the connected component to which the two + // vertices belong to. If the id is the same, it means that the + // two of them are already connected to each other via some other + // vertex, and adding this edge will create a cycle. + Vertex root1 = FindConnectedComponent(vertex1, &disjoint_set); + Vertex root2 = FindConnectedComponent(vertex2, &disjoint_set); + + if (root1 == root2) { + continue; + } + + // This edge can be added, add an edge in either direction with + // the same weight as the original graph. + const double edge_weight = graph.EdgeWeight(vertex1, vertex2); + forest->AddEdge(vertex1, vertex2, edge_weight); + forest->AddEdge(vertex2, vertex1, edge_weight); + + // Connected the two connected components by updating the + // disjoint_set structure. Always connect the connected component + // with the greater index with the connected component with the + // smaller index. This should ensure shallower trees, for quicker + // lookup. + if (root2 < root1) { + std::swap(root1, root2); + }; + + disjoint_set[root2] = root1; + } + return forest; +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_GRAPH_ALGORITHMS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc new file mode 100644 index 00000000000..bd908846362 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc @@ -0,0 +1,237 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/implicit_schur_complement.h" + +#include +#include "Eigen/Dense" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +ImplicitSchurComplement::ImplicitSchurComplement(int num_eliminate_blocks, + bool constant_sparsity, + bool preconditioner) + : num_eliminate_blocks_(num_eliminate_blocks), + constant_sparsity_(constant_sparsity), + preconditioner_(preconditioner), + A_(NULL), + D_(NULL), + b_(NULL), + block_diagonal_EtE_inverse_(NULL), + block_diagonal_FtF_inverse_(NULL) { +} + +ImplicitSchurComplement::~ImplicitSchurComplement() { +} + +void ImplicitSchurComplement::Init(const BlockSparseMatrixBase& A, + const double* D, + const double* b) { + // Since initialization is reasonably heavy, perhaps we can save on + // constructing a new object everytime. + if ((A_ == NULL) || !constant_sparsity_) { + A_.reset(new PartitionedMatrixView(A, num_eliminate_blocks_)); + } + + D_ = D; + b_ = b; + + // Initialize temporary storage and compute the block diagonals of + // E'E and F'E. + if ((!constant_sparsity_) || (block_diagonal_EtE_inverse_ == NULL)) { + block_diagonal_EtE_inverse_.reset(A_->CreateBlockDiagonalEtE()); + if (preconditioner_) { + block_diagonal_FtF_inverse_.reset(A_->CreateBlockDiagonalFtF()); + } + rhs_.resize(A_->num_cols_f()); + rhs_.setZero(); + tmp_rows_.resize(A_->num_rows()); + tmp_e_cols_.resize(A_->num_cols_e()); + tmp_e_cols_2_.resize(A_->num_cols_e()); + tmp_f_cols_.resize(A_->num_cols_f()); + } else { + A_->UpdateBlockDiagonalEtE(block_diagonal_EtE_inverse_.get()); + if (preconditioner_) { + A_->UpdateBlockDiagonalFtF(block_diagonal_FtF_inverse_.get()); + } + } + + // The block diagonals of the augmented linear system contain + // contributions from the diagonal D if it is non-null. Add that to + // the block diagonals and invert them. + if (D_ != NULL) { + AddDiagonalAndInvert(D_, block_diagonal_EtE_inverse_.get()); + if (preconditioner_) { + AddDiagonalAndInvert(D_ + A_->num_cols_e(), + block_diagonal_FtF_inverse_.get()); + } + } else { + AddDiagonalAndInvert(NULL, block_diagonal_EtE_inverse_.get()); + if (preconditioner_) { + AddDiagonalAndInvert(NULL, block_diagonal_FtF_inverse_.get()); + } + } + + // Compute the RHS of the Schur complement system. + UpdateRhs(); +} + +// Evaluate the product +// +// Sx = [F'F - F'E (E'E)^-1 E'F]x +// +// By breaking it down into individual matrix vector products +// involving the matrices E and F. This is implemented using a +// PartitionedMatrixView of the input matrix A. +void ImplicitSchurComplement::RightMultiply(const double* x, double* y) const { + // y1 = F x + tmp_rows_.setZero(); + A_->RightMultiplyF(x, tmp_rows_.data()); + + // y2 = E' y1 + tmp_e_cols_.setZero(); + A_->LeftMultiplyE(tmp_rows_.data(), tmp_e_cols_.data()); + + // y3 = -(E'E)^-1 y2 + tmp_e_cols_2_.setZero(); + block_diagonal_EtE_inverse_->RightMultiply(tmp_e_cols_.data(), + tmp_e_cols_2_.data()); + tmp_e_cols_2_ *= -1.0; + + // y1 = y1 + E y3 + A_->RightMultiplyE(tmp_e_cols_2_.data(), tmp_rows_.data()); + + // y5 = D * x + if (D_ != NULL) { + ConstVectorRef Dref(D_ + A_->num_cols_e(), num_cols()); + VectorRef(y, num_cols()) = + (Dref.array().square() * + ConstVectorRef(x, num_cols()).array()).matrix(); + } else { + VectorRef(y, num_cols()).setZero(); + } + + // y = y5 + F' y1 + A_->LeftMultiplyF(tmp_rows_.data(), y); +} + +// Given a block diagonal matrix and an optional array of diagonal +// entries D, add them to the diagonal of the matrix and compute the +// inverse of each diagonal block. +void ImplicitSchurComplement::AddDiagonalAndInvert( + const double* D, + BlockSparseMatrix* block_diagonal) { + const CompressedRowBlockStructure* block_diagonal_structure = + block_diagonal->block_structure(); + for (int r = 0; r < block_diagonal_structure->rows.size(); ++r) { + const int row_block_pos = block_diagonal_structure->rows[r].block.position; + const int row_block_size = block_diagonal_structure->rows[r].block.size; + const Cell& cell = block_diagonal_structure->rows[r].cells[0]; + MatrixRef m(block_diagonal->mutable_values() + cell.position, + row_block_size, row_block_size); + + if (D != NULL) { + ConstVectorRef d(D + row_block_pos, row_block_size); + m += d.array().square().matrix().asDiagonal(); + } + + m = m + .selfadjointView() + .ldlt() + .solve(Matrix::Identity(row_block_size, row_block_size)); + } +} + +// Similar to RightMultiply, use the block structure of the matrix A +// to compute y = (E'E)^-1 (E'b - E'F x). +void ImplicitSchurComplement::BackSubstitute(const double* x, double* y) { + const int num_cols_e = A_->num_cols_e(); + const int num_cols_f = A_->num_cols_f(); + const int num_cols = A_->num_cols(); + const int num_rows = A_->num_rows(); + + // y1 = F x + tmp_rows_.setZero(); + A_->RightMultiplyF(x, tmp_rows_.data()); + + // y2 = b - y1 + tmp_rows_ = ConstVectorRef(b_, num_rows) - tmp_rows_; + + // y3 = E' y2 + tmp_e_cols_.setZero(); + A_->LeftMultiplyE(tmp_rows_.data(), tmp_e_cols_.data()); + + // y = (E'E)^-1 y3 + VectorRef(y, num_cols).setZero(); + block_diagonal_EtE_inverse_->RightMultiply(tmp_e_cols_.data(), y); + + // The full solution vector y has two blocks. The first block of + // variables corresponds to the eliminated variables, which we just + // computed via back substitution. The second block of variables + // corresponds to the Schur complement system, so we just copy those + // values from the solution to the Schur complement. + VectorRef(y + num_cols_e, num_cols_f) = ConstVectorRef(x, num_cols_f); +} + +// Compute the RHS of the Schur complement system. +// +// rhs = F'b - F'E (E'E)^-1 E'b +// +// Like BackSubstitute, we use the block structure of A to implement +// this using a series of matrix vector products. +void ImplicitSchurComplement::UpdateRhs() { + // y1 = E'b + tmp_e_cols_.setZero(); + A_->LeftMultiplyE(b_, tmp_e_cols_.data()); + + // y2 = (E'E)^-1 y1 + Vector y2 = Vector::Zero(A_->num_cols_e()); + block_diagonal_EtE_inverse_->RightMultiply(tmp_e_cols_.data(), y2.data()); + + // y3 = E y2 + tmp_rows_.setZero(); + A_->RightMultiplyE(y2.data(), tmp_rows_.data()); + + // y3 = b - y3 + tmp_rows_ = ConstVectorRef(b_, A_->num_rows()) - tmp_rows_; + + // rhs = F' y3 + rhs_.setZero(); + A_->LeftMultiplyF(tmp_rows_.data(), rhs_.data()); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h new file mode 100644 index 00000000000..37a319f9c57 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h @@ -0,0 +1,176 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// An iterative solver for solving the Schur complement/reduced camera +// linear system that arise in SfM problems. + +#ifndef CERES_INTERNAL_IMPLICIT_SCHUR_COMPLEMENT_H_ +#define CERES_INTERNAL_IMPLICIT_SCHUR_COMPLEMENT_H_ + +#include "ceres/linear_operator.h" +#include "ceres/partitioned_matrix_view.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class BlockSparseMatrix; +class BlockSparseMatrixBase; + +// This class implements various linear algebraic operations related +// to the Schur complement without explicitly forming it. +// +// +// Given a reactangular linear system Ax = b, where +// +// A = [E F] +// +// The normal equations are given by +// +// A'Ax = A'b +// +// |E'E E'F||y| = |E'b| +// |F'E F'F||z| |F'b| +// +// and the Schur complement system is given by +// +// [F'F - F'E (E'E)^-1 E'F] z = F'b - F'E (E'E)^-1 E'b +// +// Now if we wish to solve Ax = b in the least squares sense, one way +// is to form this Schur complement system and solve it using +// Preconditioned Conjugate Gradients. +// +// The key operation in a conjugate gradient solver is the evaluation of the +// matrix vector product with the Schur complement +// +// S = F'F - F'E (E'E)^-1 E'F +// +// It is straightforward to see that matrix vector products with S can +// be evaluated without storing S in memory. Instead, given (E'E)^-1 +// (which for our purposes is an easily inverted block diagonal +// matrix), it can be done in terms of matrix vector products with E, +// F and (E'E)^-1. This class implements this functionality and other +// auxilliary bits needed to implement a CG solver on the Schur +// complement using the PartitionedMatrixView object. +// +// THREAD SAFETY: This class is nqot thread safe. In particular, the +// RightMultiply (and the LeftMultiply) methods are not thread safe as +// they depend on mutable arrays used for the temporaries needed to +// compute the product y += Sx; +class ImplicitSchurComplement : public LinearOperator { + public: + // num_eliminate_blocks is the number of E blocks in the matrix + // A. + // + // constant_sparsity indicates if across calls to Init, the sparsity + // structure of the matrix A remains constant or not. This makes for + // significant savings across multiple matrices A, e.g. when used in + // conjunction with an optimization algorithm. + // + // preconditioner indicates whether the inverse of the matrix F'F + // should be computed or not as a preconditioner for the Schur + // Complement. + // + // TODO(sameeragarwal): Get rid of the two bools below and replace + // them with enums. + ImplicitSchurComplement(int num_eliminate_blocks, + bool constant_sparsity, + bool preconditioner); + virtual ~ImplicitSchurComplement(); + + // Initialize the Schur complement for a linear least squares + // problem of the form + // + // |A | x = |b| + // |diag(D)| |0| + // + // If D is null, then it is treated as a zero dimensional matrix. It + // is important that the matrix A have a BlockStructure object + // associated with it and has a block structure that is compatible + // with the SchurComplement solver. + void Init(const BlockSparseMatrixBase& A, const double* D, const double* b); + + // y += Sx, where S is the Schur complement. + virtual void RightMultiply(const double* x, double* y) const; + + // The Schur complement is a symmetric positive definite matrix, + // thus the left and right multiply operators are the same. + virtual void LeftMultiply(const double* x, double* y) const { + RightMultiply(x, y); + } + + // y = (E'E)^-1 (E'b - E'F x). Given an estimate of the solution to + // the Schur complement system, this method computes the value of + // the e_block variables that were eliminated to form the Schur + // complement. + void BackSubstitute(const double* x, double* y); + + virtual int num_rows() const { return A_->num_cols_f(); } + virtual int num_cols() const { return A_->num_cols_f(); } + const Vector& rhs() const { return rhs_; } + + const BlockSparseMatrix* block_diagonal_EtE_inverse() const { + return block_diagonal_EtE_inverse_.get(); + } + + const BlockSparseMatrix* block_diagonal_FtF_inverse() const { + return block_diagonal_FtF_inverse_.get(); + } + + private: + void AddDiagonalAndInvert(const double* D, BlockSparseMatrix* matrix); + void UpdateRhs(); + + int num_eliminate_blocks_; + bool constant_sparsity_; + bool preconditioner_; + + scoped_ptr A_; + const double* D_; + const double* b_; + + scoped_ptr block_diagonal_EtE_inverse_; + scoped_ptr block_diagonal_FtF_inverse_; + + Vector rhs_; + + // Temporary storage vectors used to implement RightMultiply. + mutable Vector tmp_rows_; + mutable Vector tmp_e_cols_; + mutable Vector tmp_e_cols_2_; + mutable Vector tmp_f_cols_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_IMPLICIT_SCHUR_COMPLEMENT_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/integral_types.h b/extern/libmv/third_party/ceres/internal/ceres/integral_types.h new file mode 100644 index 00000000000..01e04937e3e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/integral_types.h @@ -0,0 +1,92 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Portable typedefs for various fixed-size integers. Uses template +// metaprogramming instead of fragile compiler defines. + +#ifndef CERES_INTERNAL_INTEGRAL_TYPES_H_ +#define CERES_INTERNAL_INTEGRAL_TYPES_H_ + +namespace ceres { +namespace internal { + +// Compile time ternary on types. +template +struct Ternary { + typedef kTrueType type; +}; +template +struct Ternary { + typedef kFalseType type; +}; + +#define CERES_INTSIZE(TYPE) \ + typename Ternary +struct Integer { + typedef + CERES_INTSIZE(char) + CERES_INTSIZE(short) + CERES_INTSIZE(int) + CERES_INTSIZE(long int) + CERES_INTSIZE(long long) + void>::type >::type >::type >::type >::type + type; +}; + +template +struct UnsignedInteger { + typedef + CERES_INTSIZE(unsigned char) + CERES_INTSIZE(unsigned short) + CERES_INTSIZE(unsigned int) + CERES_INTSIZE(unsigned long int) + CERES_INTSIZE(unsigned long long) + void>::type >::type >::type >::type >::type + type; +}; + +#undef CERES_INTSIZE + +typedef Integer< 8>::type int8; +typedef Integer<16>::type int16; +typedef Integer<32>::type int32; +typedef Integer<64>::type int64; + +typedef UnsignedInteger< 8>::type uint8; +typedef UnsignedInteger<16>::type uint16; +typedef UnsignedInteger<32>::type uint32; +typedef UnsignedInteger<64>::type uint64; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_INTEGRAL_TYPES_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc new file mode 100644 index 00000000000..51303195317 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc @@ -0,0 +1,150 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/iterative_schur_complement_solver.h" + +#include +#include +#include + +#include +#include "Eigen/Dense" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/conjugate_gradients_solver.h" +#include "ceres/implicit_schur_complement.h" +#include "ceres/linear_solver.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/visibility_based_preconditioner.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/linear_solver.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/types.h" +#include "ceres/visibility_based_preconditioner.h" + +namespace ceres { +namespace internal { + +IterativeSchurComplementSolver::IterativeSchurComplementSolver( + const LinearSolver::Options& options) + : options_(options) { +} + +IterativeSchurComplementSolver::~IterativeSchurComplementSolver() { +} + +LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( + BlockSparseMatrixBase* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + CHECK_NOTNULL(A->block_structure()); + + // Initialize a ImplicitSchurComplement object. + if ((schur_complement_ == NULL) || (!options_.constant_sparsity)) { + schur_complement_.reset( + new ImplicitSchurComplement(options_.num_eliminate_blocks, + options_.constant_sparsity, + options_.preconditioner_type == JACOBI)); + } + schur_complement_->Init(*A, per_solve_options.D, b); + + // Initialize the solution to the Schur complement system to zero. + // + // TODO(sameeragarwal): There maybe a better initialization than an + // all zeros solution. Explore other cheap starting points. + reduced_linear_system_solution_.resize(schur_complement_->num_rows()); + reduced_linear_system_solution_.setZero(); + + // Instantiate a conjugate gradient solver that runs on the Schur complement + // matrix with the block diagonal of the matrix F'F as the preconditioner. + LinearSolver::Options cg_options; + cg_options.max_num_iterations = options_.max_num_iterations; + ConjugateGradientsSolver cg_solver(cg_options); + LinearSolver::PerSolveOptions cg_per_solve_options; + + cg_per_solve_options.r_tolerance = per_solve_options.r_tolerance; + cg_per_solve_options.q_tolerance = per_solve_options.q_tolerance; + + bool is_preconditioner_good = false; + switch (options_.preconditioner_type) { + case IDENTITY: + is_preconditioner_good = true; + break; + case JACOBI: + // We need to strip the constness of the block_diagonal_FtF_inverse + // matrix here because the only other way to initialize the struct + // cg_solve_options would be to add a constructor to it. We know + // that the only method ever called on the preconditioner is the + // RightMultiply which is a const method so we don't need to worry + // about the object getting modified. + cg_per_solve_options.preconditioner = + const_cast( + schur_complement_->block_diagonal_FtF_inverse()); + is_preconditioner_good = true; + break; + case SCHUR_JACOBI: + case CLUSTER_JACOBI: + case CLUSTER_TRIDIAGONAL: + if (visibility_based_preconditioner_.get() == NULL) { + visibility_based_preconditioner_.reset( + new VisibilityBasedPreconditioner(*A->block_structure(), options_)); + } + is_preconditioner_good = + visibility_based_preconditioner_->Compute(*A, per_solve_options.D); + cg_per_solve_options.preconditioner = + visibility_based_preconditioner_.get(); + break; + default: + LOG(FATAL) << "Unknown Preconditioner Type"; + } + + LinearSolver::Summary cg_summary; + cg_summary.num_iterations = 0; + cg_summary.termination_type = FAILURE; + + if (is_preconditioner_good) { + cg_summary = cg_solver.Solve(schur_complement_.get(), + schur_complement_->rhs().data(), + cg_per_solve_options, + reduced_linear_system_solution_.data()); + if (cg_summary.termination_type != FAILURE) { + schur_complement_->BackSubstitute( + reduced_linear_system_solution_.data(), x); + } + } + + VLOG(2) << "CG Iterations : " << cg_summary.num_iterations; + return cg_summary; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h new file mode 100644 index 00000000000..cfeb65e1eec --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h @@ -0,0 +1,94 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_ITERATIVE_SCHUR_COMPLEMENT_SOLVER_H_ +#define CERES_INTERNAL_ITERATIVE_SCHUR_COMPLEMENT_SOLVER_H_ + +#include "ceres/linear_solver.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class BlockSparseMatrix; +class BlockSparseMatrixBase; +class ImplicitSchurComplement; +class VisibilityBasedPreconditioner; + +// This class implements an iterative solver for the linear least +// squares problems that have a bi-partitte sparsity structure common +// to Structure from Motion problems. +// +// The algorithm used by this solver was developed in a series of +// papers - "Agarwal et al, Bundle Adjustment in the Large, ECCV 2010" +// and "Wu et al, Multicore Bundle Adjustment, submitted to CVPR +// 2011" at the Univeristy of Washington. +// +// The key idea is that one can run Conjugate Gradients on the Schur +// Complement system without explicitly forming the Schur Complement +// in memory. The heavy lifting for this is done by the +// ImplicitSchurComplement class. Not forming the Schur complement in +// memory and factoring it results in substantial savings in time and +// memory. Further, iterative solvers like this open up the +// possibility of solving the Newton equations in a non-linear solver +// only approximately and terminating early, thereby saving even more +// time. +// +// For the curious, running CG on the Schur complement is the same as +// running CG on the Normal Equations with an SSOR preconditioner. For +// a proof of this fact and others related to this solver please see +// the section on Domain Decomposition Methods in Saad's book +// "Iterative Methods for Sparse Linear Systems". +class IterativeSchurComplementSolver : public BlockSparseMatrixBaseSolver { + public: + explicit IterativeSchurComplementSolver( + const LinearSolver::Options& options); + + virtual ~IterativeSchurComplementSolver(); + + private: + virtual LinearSolver::Summary SolveImpl( + BlockSparseMatrixBase* A, + const double* b, + const LinearSolver::PerSolveOptions& options, + double* x); + + LinearSolver::Options options_; + scoped_ptr schur_complement_; + scoped_ptr visibility_based_preconditioner_; + Vector reduced_linear_system_solution_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_ITERATIVE_SCHUR_COMPLEMENT_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc new file mode 100644 index 00000000000..3ad359e63e4 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc @@ -0,0 +1,620 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Implementation of a simple LM algorithm which uses the step sizing +// rule of "Methods for Nonlinear Least Squares" by K. Madsen, +// H.B. Nielsen and O. Tingleff. Available to download from +// +// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf +// +// The basic algorithm described in this note is an exact step +// algorithm that depends on the Newton(LM) step being solved exactly +// in each iteration. When a suitable iterative solver is available to +// solve the Newton(LM) step, the algorithm will automatically switch +// to an inexact step solution method. This trades some slowdown in +// convergence for significant savings in solve time and memory +// usage. Our implementation of the Truncated Newton algorithm follows +// the discussion and recommendataions in "Stephen G. Nash, A Survey +// of Truncated Newton Methods, Journal of Computational and Applied +// Mathematics, 124(1-2), 45-59, 2000. + +#include "ceres/levenberg_marquardt.h" + +#include +#include +#include +#include +#include +#include + +#include +#include "Eigen/Core" +#include "ceres/evaluator.h" +#include "ceres/file.h" +#include "ceres/linear_solver.h" +#include "ceres/matrix_proto.h" +#include "ceres/sparse_matrix.h" +#include "ceres/stringprintf.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { +namespace { + +// Numbers for clamping the size of the LM diagonal. The size of these +// numbers is heuristic. We will probably be adjusting them in the +// future based on more numerical experience. With jacobi scaling +// enabled, these numbers should be all but redundant. +const double kMinLevenbergMarquardtDiagonal = 1e-6; +const double kMaxLevenbergMarquardtDiagonal = 1e32; + +// Small constant for various floating point issues. +const double kEpsilon = 1e-12; + +// Number of times the linear solver should be retried in case of +// numerical failure. The retries are done by exponentially scaling up +// mu at each retry. This leads to stronger and stronger +// regularization making the linear least squares problem better +// conditioned at each retry. +const int kMaxLinearSolverRetries = 5; + +// D = 1/sqrt(diag(J^T * J)) +void EstimateScale(const SparseMatrix& jacobian, double* D) { + CHECK_NOTNULL(D); + jacobian.SquaredColumnNorm(D); + for (int i = 0; i < jacobian.num_cols(); ++i) { + D[i] = 1.0 / (kEpsilon + sqrt(D[i])); + } +} + +// D = diag(J^T * J) +void LevenbergMarquardtDiagonal(const SparseMatrix& jacobian, + double* D) { + CHECK_NOTNULL(D); + jacobian.SquaredColumnNorm(D); + for (int i = 0; i < jacobian.num_cols(); ++i) { + D[i] = min(max(D[i], kMinLevenbergMarquardtDiagonal), + kMaxLevenbergMarquardtDiagonal); + } +} + +string DumpLinearSolverProblem( + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + const Minimizer::Options& solver_options) { + if (solver_options.lsqp_dump_format == "ascii") { + // Dump to the screen instead of to file. Useful for debugging. + Matrix AA; + A->ToDenseMatrix(&AA); + LOG(INFO) << "A^T: \n" << AA.transpose(); + if (D) { + LOG(INFO) << "A's appended diagonal:\n" + << ConstVectorRef(D, A->num_cols()); + } + LOG(INFO) << "b: \n" << ConstVectorRef(b, A->num_rows()); + LOG(INFO) << "x: \n" << ConstVectorRef(x, A->num_cols()); + return ""; + } +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + LinearLeastSquaresProblemProto lsqp; + A->ToProto(lsqp.mutable_a()); + for (int i = 0; i < A->num_rows(); ++i) { + lsqp.add_b(b[i]); + } + if (D) { + for (int i = 0; i < A->num_cols(); ++i) { + lsqp.add_d(D[i]); + } + } + if (x) { + for (int i = 0; i < A->num_cols(); ++i) { + lsqp.add_x(x[i]); + } + } + + lsqp.set_num_eliminate_blocks(solver_options.num_eliminate_blocks); + + CHECK(solver_options.lsqp_dump_format.size()); + string filename = + StringPrintf(solver_options.lsqp_dump_format.c_str(), // NOLINT + iteration); + VLOG(1) << "Dumping least squares problem for iteration " << iteration + << " to disk. File: " << filename; + WriteStringToFileOrDie(lsqp.SerializeAsString(), filename); + VLOG(2) << "Done dumping to disk"; + return filename; +#else + LOG(ERROR) << "Dumping least squares problems is only " + << "supported when Ceres is compiled with " + << "protocol buffer support."; + return ""; +#endif +} + +bool RunCallback(IterationCallback* callback, + const IterationSummary& iteration_summary, + Solver::Summary* summary) { + const CallbackReturnType status = (*callback)(iteration_summary); + switch (status) { + case SOLVER_TERMINATE_SUCCESSFULLY: + summary->termination_type = USER_SUCCESS; + VLOG(1) << "Terminating on USER_SUCCESS."; + return false; + case SOLVER_ABORT: + summary->termination_type = USER_ABORT; + VLOG(1) << "Terminating on USER_ABORT."; + return false; + case SOLVER_CONTINUE: + return true; + default: + LOG(FATAL) << "Unknown status returned by callback: " + << status; + return NULL; + } +} + +} // namespace + +LevenbergMarquardt::~LevenbergMarquardt() {} + +void LevenbergMarquardt::Minimize(const Minimizer::Options& options, + Evaluator* evaluator, + LinearSolver* linear_solver, + const double* initial_parameters, + double* final_parameters, + Solver::Summary* summary) { + time_t start_time = time(NULL); + const int num_parameters = evaluator->NumParameters(); + const int num_effective_parameters = evaluator->NumEffectiveParameters(); + const int num_residuals = evaluator->NumResiduals(); + + summary->termination_type = NO_CONVERGENCE; + summary->num_successful_steps = 0; + summary->num_unsuccessful_steps = 0; + + // Allocate the various vectors needed by the algorithm. + memcpy(final_parameters, initial_parameters, + num_parameters * sizeof(*initial_parameters)); + + VectorRef x(final_parameters, num_parameters); + Vector x_new(num_parameters); + + Vector lm_step(num_effective_parameters); + Vector gradient(num_effective_parameters); + Vector scaled_gradient(num_effective_parameters); + // Jacobi scaling vector + Vector scale(num_effective_parameters); + + Vector f_model(num_residuals); + Vector f(num_residuals); + Vector f_new(num_residuals); + Vector D(num_parameters); + Vector muD(num_parameters); + + // Ask the Evaluator to create the jacobian matrix. The sparsity + // pattern of this matrix is going to remain constant, so we only do + // this once and then re-use this matrix for all subsequent Jacobian + // computations. + scoped_ptr jacobian(evaluator->CreateJacobian()); + + double x_norm = x.norm(); + + double cost = 0.0; + D.setOnes(); + f.setZero(); + + // Do initial cost and Jacobian evaluation. + if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) { + LOG(WARNING) << "Failed to compute residuals and Jacobian. " + << "Terminating."; + summary->termination_type = NUMERICAL_FAILURE; + return; + } + + if (options.jacobi_scaling) { + EstimateScale(*jacobian, scale.data()); + jacobian->ScaleColumns(scale.data()); + } else { + scale.setOnes(); + } + + // This is a poor way to do this computation. Even if fixed_cost is + // zero, because we are subtracting two possibly large numbers, we + // are depending on exact cancellation to give us a zero here. But + // initial_cost and cost have been computed by two different + // evaluators. One which runs on the whole problem (in + // solver_impl.cc) in single threaded mode and another which runs + // here on the reduced problem, so fixed_cost can (and does) contain + // some numerical garbage with a relative magnitude of 1e-14. + // + // The right way to do this, would be to compute the fixed cost on + // just the set of residual blocks which are held constant and were + // removed from the original problem when the reduced problem was + // constructed. + summary->fixed_cost = summary->initial_cost - cost; + + double model_cost = f.squaredNorm() / 2.0; + double total_cost = summary->fixed_cost + cost; + + scaled_gradient.setZero(); + jacobian->LeftMultiply(f.data(), scaled_gradient.data()); + gradient = scaled_gradient.array() / scale.array(); + + double gradient_max_norm = gradient.lpNorm(); + // We need the max here to guard againt the gradient being zero. + const double gradient_max_norm_0 = max(gradient_max_norm, kEpsilon); + double gradient_tolerance = options.gradient_tolerance * gradient_max_norm_0; + + double mu = options.tau; + double nu = 2.0; + int iteration = 0; + double actual_cost_change = 0.0; + double step_norm = 0.0; + double relative_decrease = 0.0; + + // Insane steps are steps which are not sane, i.e. there is some + // numerical kookiness going on with them. There are various reasons + // for this kookiness, some easier to diagnose then others. From the + // point of view of the non-linear solver, they are steps which + // cannot be used. We return with NUMERICAL_FAILURE after + // kMaxLinearSolverRetries consecutive insane steps. + bool step_is_sane = false; + int num_consecutive_insane_steps = 0; + + // Whether the step resulted in a sufficient decrease in the + // objective function when compared to the decrease in the value of + // the lineariztion. + bool step_is_successful = false; + + // Parse the iterations for which to dump the linear problem. + vector iterations_to_dump = options.lsqp_iterations_to_dump; + sort(iterations_to_dump.begin(), iterations_to_dump.end()); + + IterationSummary iteration_summary; + iteration_summary.iteration = iteration; + iteration_summary.step_is_successful = false; + iteration_summary.cost = total_cost; + iteration_summary.cost_change = actual_cost_change; + iteration_summary.gradient_max_norm = gradient_max_norm; + iteration_summary.step_norm = step_norm; + iteration_summary.relative_decrease = relative_decrease; + iteration_summary.mu = mu; + iteration_summary.eta = options.eta; + iteration_summary.linear_solver_iterations = 0; + iteration_summary.linear_solver_time_sec = 0.0; + iteration_summary.iteration_time_sec = (time(NULL) - start_time); + if (options.logging_type >= PER_MINIMIZER_ITERATION) { + summary->iterations.push_back(iteration_summary); + } + + // Check if the starting point is an optimum. + VLOG(2) << "Gradient max norm: " << gradient_max_norm + << " tolerance: " << gradient_tolerance + << " ratio: " << gradient_max_norm / gradient_max_norm_0 + << " tolerance: " << options.gradient_tolerance; + if (gradient_max_norm <= gradient_tolerance) { + summary->termination_type = GRADIENT_TOLERANCE; + VLOG(1) << "Terminating on GRADIENT_TOLERANCE. " + << "Relative gradient max norm: " + << gradient_max_norm / gradient_max_norm_0 + << " <= " << options.gradient_tolerance; + return; + } + + // Call the various callbacks. + for (int i = 0; i < options.callbacks.size(); ++i) { + if (!RunCallback(options.callbacks[i], iteration_summary, summary)) { + return; + } + } + + // We only need the LM diagonal if we are actually going to do at + // least one iteration of the optimization. So we wait to do it + // until now. + LevenbergMarquardtDiagonal(*jacobian, D.data()); + + while ((iteration < options.max_num_iterations) && + (time(NULL) - start_time) <= options.max_solver_time_sec) { + time_t iteration_start_time = time(NULL); + step_is_sane = false; + step_is_successful = false; + + IterationSummary iteration_summary; + // The while loop here is just to provide an easily breakable + // control structure. We are guaranteed to always exit this loop + // at the end of one iteration or before. + while (1) { + muD = (mu * D).array().sqrt(); + LinearSolver::PerSolveOptions solve_options; + solve_options.D = muD.data(); + solve_options.q_tolerance = options.eta; + // Disable r_tolerance checking. Since we only care about + // termination via the q_tolerance. As Nash and Sofer show, + // r_tolerance based termination is essentially useless in + // Truncated Newton methods. + solve_options.r_tolerance = -1.0; + + const time_t linear_solver_start_time = time(NULL); + LinearSolver::Summary linear_solver_summary = + linear_solver->Solve(jacobian.get(), + f.data(), + solve_options, + lm_step.data()); + iteration_summary.linear_solver_time_sec = + (time(NULL) - linear_solver_start_time); + iteration_summary.linear_solver_iterations = + linear_solver_summary.num_iterations; + + if (binary_search(iterations_to_dump.begin(), + iterations_to_dump.end(), + iteration)) { + DumpLinearSolverProblem(iteration, + jacobian.get(), + muD.data(), + f.data(), + lm_step.data(), + options); + } + + // We ignore the case where the linear solver did not converge, + // since the partial solution computed by it still maybe of use, + // and there is no reason to ignore it, especially since we + // spent so much time computing it. + if ((linear_solver_summary.termination_type != TOLERANCE) && + (linear_solver_summary.termination_type != MAX_ITERATIONS)) { + VLOG(1) << "Linear solver failure: retrying with a higher mu"; + break; + } + + step_norm = (lm_step.array() * scale.array()).matrix().norm(); + + // Check step length based convergence. If the step length is + // too small, then we are done. + const double step_size_tolerance = options.parameter_tolerance * + (x_norm + options.parameter_tolerance); + + VLOG(2) << "Step size: " << step_norm + << " tolerance: " << step_size_tolerance + << " ratio: " << step_norm / step_size_tolerance + << " tolerance: " << options.parameter_tolerance; + if (step_norm <= options.parameter_tolerance * + (x_norm + options.parameter_tolerance)) { + summary->termination_type = PARAMETER_TOLERANCE; + VLOG(1) << "Terminating on PARAMETER_TOLERANCE." + << "Relative step size: " << step_norm / step_size_tolerance + << " <= " << options.parameter_tolerance; + return; + } + + Vector delta = -(lm_step.array() * scale.array()).matrix(); + if (!evaluator->Plus(x.data(), delta.data(), x_new.data())) { + LOG(WARNING) << "Failed to compute Plus(x, delta, x_plus_delta). " + << "Terminating."; + summary->termination_type = NUMERICAL_FAILURE; + return; + } + + double cost_new = 0.0; + if (!evaluator->Evaluate(x_new.data(), &cost_new, NULL, NULL)) { + LOG(WARNING) << "Failed to compute the value of the objective " + << "function. Terminating."; + summary->termination_type = NUMERICAL_FAILURE; + return; + } + + f_model.setZero(); + jacobian->RightMultiply(lm_step.data(), f_model.data()); + const double model_cost_new = + (f.segment(0, num_residuals) - f_model).squaredNorm() / 2; + + actual_cost_change = cost - cost_new; + double model_cost_change = model_cost - model_cost_new; + + VLOG(2) << "[Model cost] current: " << model_cost + << " new : " << model_cost_new + << " change: " << model_cost_change; + + VLOG(2) << "[Nonlinear cost] current: " << cost + << " new : " << cost_new + << " change: " << actual_cost_change + << " relative change: " << fabs(actual_cost_change) / cost + << " tolerance: " << options.function_tolerance; + + // In exact arithmetic model_cost_change should never be + // negative. But due to numerical precision issues, we may end up + // with a small negative number. model_cost_change which are + // negative and large in absolute value are indicative of a + // numerical failure in the solver. + if (model_cost_change < -kEpsilon) { + VLOG(1) << "Model cost change is negative.\n" + << "Current : " << model_cost + << " new : " << model_cost_new + << " change: " << model_cost_change << "\n"; + break; + } + + // If we have reached this far, then we are willing to trust the + // numerical quality of the step. + step_is_sane = true; + num_consecutive_insane_steps = 0; + + // Check function value based convergence. + if (fabs(actual_cost_change) < options.function_tolerance * cost) { + VLOG(1) << "Termination on FUNCTION_TOLERANCE." + << " Relative cost change: " << fabs(actual_cost_change) / cost + << " tolerance: " << options.function_tolerance; + summary->termination_type = FUNCTION_TOLERANCE; + return; + } + + // Clamp model_cost_change at kEpsilon from below. + if (model_cost_change < kEpsilon) { + VLOG(1) << "Clamping model cost change " << model_cost_change + << " to " << kEpsilon; + model_cost_change = kEpsilon; + } + + relative_decrease = actual_cost_change / model_cost_change; + VLOG(2) << "actual_cost_change / model_cost_change = " + << relative_decrease; + + if (relative_decrease < options.min_relative_decrease) { + VLOG(2) << "Unsuccessful step."; + break; + } + + VLOG(2) << "Successful step."; + + ++summary->num_successful_steps; + x = x_new; + x_norm = x.norm(); + + if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) { + LOG(WARNING) << "Failed to compute residuals and jacobian. " + << "Terminating."; + summary->termination_type = NUMERICAL_FAILURE; + return; + } + + if (options.jacobi_scaling) { + jacobian->ScaleColumns(scale.data()); + } + + model_cost = f.squaredNorm() / 2.0; + LevenbergMarquardtDiagonal(*jacobian, D.data()); + scaled_gradient.setZero(); + jacobian->LeftMultiply(f.data(), scaled_gradient.data()); + gradient = scaled_gradient.array() / scale.array(); + gradient_max_norm = gradient.lpNorm(); + + // Check gradient based convergence. + VLOG(2) << "Gradient max norm: " << gradient_max_norm + << " tolerance: " << gradient_tolerance + << " ratio: " << gradient_max_norm / gradient_max_norm_0 + << " tolerance: " << options.gradient_tolerance; + if (gradient_max_norm <= gradient_tolerance) { + summary->termination_type = GRADIENT_TOLERANCE; + VLOG(1) << "Terminating on GRADIENT_TOLERANCE. " + << "Relative gradient max norm: " + << gradient_max_norm / gradient_max_norm_0 + << " <= " << options.gradient_tolerance + << " (tolerance)."; + return; + } + + mu = mu * max(1.0 / 3.0, 1 - pow(2 * relative_decrease - 1, 3)); + nu = 2.0; + step_is_successful = true; + break; + } + + if (!step_is_sane) { + ++num_consecutive_insane_steps; + } + + if (num_consecutive_insane_steps == kMaxLinearSolverRetries) { + VLOG(1) << "Too many consecutive retries; ending with numerical fail."; + summary->termination_type = NUMERICAL_FAILURE; + + if (!options.crash_and_dump_lsqp_on_failure) { + return; + } + + // Dump debugging information to disk. + CHECK(!options.lsqp_dump_format.empty()) + << "Dumping the linear least squares problem on crash " + << "requires Solver::Options::lsqp_dump_format set a " + << "filename"; + CHECK_NE(options.lsqp_dump_format, "ascii") + << "Dumping the linear least squares problem on crash " + << "requires Solver::Options::lsqp_dump_format set a " + << "filename"; + + const string filename = DumpLinearSolverProblem(iteration, + jacobian.get(), + muD.data(), + f.data(), + lm_step.data(), + options); + LOG(FATAL) << "Linear least squares problem saved to " << filename + << " please provide this to the Ceres developers for " + << " debugging along with the v=2 log."; + return; + } + + if (!step_is_successful) { + // Either the step did not lead to a decrease in cost or there + // was numerical failure. In either case we will scale mu up and + // retry. If it was a numerical failure, we hope that the + // stronger regularization will make the linear system better + // conditioned. If it was numerically sane, but there was no + // decrease in cost, then increasing mu reduces the size of the + // trust region and we look for a decrease closer to the + // linearization point. + ++summary->num_unsuccessful_steps; + mu = mu * nu; + nu = 2 * nu; + } + + ++iteration; + + total_cost = summary->fixed_cost + cost; + + iteration_summary.iteration = iteration; + iteration_summary.step_is_successful = step_is_successful; + iteration_summary.cost = total_cost; + iteration_summary.cost_change = actual_cost_change; + iteration_summary.gradient_max_norm = gradient_max_norm; + iteration_summary.step_norm = step_norm; + iteration_summary.relative_decrease = relative_decrease; + iteration_summary.mu = mu; + iteration_summary.eta = options.eta; + iteration_summary.iteration_time_sec = (time(NULL) - iteration_start_time); + + if (options.logging_type >= PER_MINIMIZER_ITERATION) { + summary->iterations.push_back(iteration_summary); + } + + // Call the various callbacks. + for (int i = 0; i < options.callbacks.size(); ++i) { + if (!RunCallback(options.callbacks[i], iteration_summary, summary)) { + return; + } + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h new file mode 100644 index 00000000000..d00bb9095be --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h @@ -0,0 +1,65 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Implmentation of Levenberg Marquardt algorithm based on "Methods for +// Nonlinear Least Squares" by K. Madsen, H.B. Nielsen and +// O. Tingleff. Available to download from +// +// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf +// + +#ifndef CERES_INTERNAL_LEVENBERG_MARQUARDT_H_ +#define CERES_INTERNAL_LEVENBERG_MARQUARDT_H_ + +#include "ceres/minimizer.h" +#include "ceres/solver.h" + +namespace ceres { +namespace internal { + +class Evaluator; +class LinearSolver; + +class LevenbergMarquardt : public Minimizer { + public: + virtual ~LevenbergMarquardt(); + + virtual void Minimize(const Minimizer::Options& options, + Evaluator* evaluator, + LinearSolver* linear_solver, + const double* initial_parameters, + double* final_parameters, + Solver::Summary* summary); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LEVENBERG_MARQUARDT_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc new file mode 100644 index 00000000000..9fc5ff8a1c7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc @@ -0,0 +1,574 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/linear_least_squares_problems.h" + +#include +#include +#include +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/file.h" +#include "ceres/matrix_proto.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id) { + switch (id) { + case 0: + return LinearLeastSquaresProblem0(); + case 1: + return LinearLeastSquaresProblem1(); + case 2: + return LinearLeastSquaresProblem2(); + case 3: + return LinearLeastSquaresProblem3(); + default: + LOG(FATAL) << "Unknown problem id requested " << id; + } + return NULL; +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile( + const string& filename) { + LinearLeastSquaresProblemProto problem_proto; + { + string serialized_proto; + ReadFileToStringOrDie(filename, &serialized_proto); + CHECK(problem_proto.ParseFromString(serialized_proto)); + } + + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + const SparseMatrixProto& A = problem_proto.a(); + + if (A.has_block_matrix()) { + problem->A.reset(new BlockSparseMatrix(A)); + } else if (A.has_triplet_matrix()) { + problem->A.reset(new TripletSparseMatrix(A)); + } else { + problem->A.reset(new CompressedRowSparseMatrix(A)); + } + + if (problem_proto.b_size() > 0) { + problem->b.reset(new double[problem_proto.b_size()]); + for (int i = 0; i < problem_proto.b_size(); ++i) { + problem->b[i] = problem_proto.b(i); + } + } + + if (problem_proto.d_size() > 0) { + problem->D.reset(new double[problem_proto.d_size()]); + for (int i = 0; i < problem_proto.d_size(); ++i) { + problem->D[i] = problem_proto.d(i); + } + } + + if (problem_proto.d_size() > 0) { + if (problem_proto.x_size() > 0) { + problem->x_D.reset(new double[problem_proto.x_size()]); + for (int i = 0; i < problem_proto.x_size(); ++i) { + problem->x_D[i] = problem_proto.x(i); + } + } + } else { + if (problem_proto.x_size() > 0) { + problem->x.reset(new double[problem_proto.x_size()]); + for (int i = 0; i < problem_proto.x_size(); ++i) { + problem->x[i] = problem_proto.x(i); + } + } + } + + problem->num_eliminate_blocks = 0; + if (problem_proto.has_num_eliminate_blocks()) { + problem->num_eliminate_blocks = problem_proto.num_eliminate_blocks(); + } + + return problem; +} +#else +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile( + const string& filename) { + LOG(FATAL) + << "Loading a least squares problem from disk requires " + << "Ceres to be built with Protocol Buffers support."; + return NULL; +} +#endif // CERES_DONT_HAVE_PROTOCOL_BUFFERS + +/* +A = [1 2] + [3 4] + [6 -10] + +b = [ 8 + 18 + -18] + +x = [2 + 3] + +D = [1 + 2] + +x_D = [1.78448275; + 2.82327586;] + */ +LinearLeastSquaresProblem* LinearLeastSquaresProblem0() { + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + + TripletSparseMatrix* A = new TripletSparseMatrix(3, 2, 6); + problem->b.reset(new double[3]); + problem->D.reset(new double[2]); + + problem->x.reset(new double[2]); + problem->x_D.reset(new double[2]); + + int* Ai = A->mutable_rows(); + int* Aj = A->mutable_cols(); + double* Ax = A->mutable_values(); + + int counter = 0; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j< 2; ++j) { + Ai[counter]=i; + Aj[counter]=j; + ++counter; + } + }; + + Ax[0] = 1.; + Ax[1] = 2.; + Ax[2] = 3.; + Ax[3] = 4.; + Ax[4] = 6; + Ax[5] = -10; + A->set_num_nonzeros(6); + problem->A.reset(A); + + problem->b[0] = 8; + problem->b[1] = 18; + problem->b[2] = -18; + + problem->x[0] = 2.0; + problem->x[1] = 3.0; + + problem->D[0] = 1; + problem->D[1] = 2; + + problem->x_D[0] = 1.78448275; + problem->x_D[1] = 2.82327586; + return problem; +} + + +/* + A = [1 0 | 2 0 0 + 3 0 | 0 4 0 + 0 5 | 0 0 6 + 0 7 | 8 0 0 + 0 9 | 1 0 0 + 0 0 | 1 1 1] + + b = [0 + 1 + 2 + 3 + 4 + 5] + + c = A'* b = [ 3 + 67 + 33 + 9 + 17] + + A'A = [10 0 2 12 0 + 0 155 65 0 30 + 2 65 70 1 1 + 12 0 1 17 1 + 0 30 1 1 37] + + S = [ 42.3419 -1.4000 -11.5806 + -1.4000 2.6000 1.0000 + 11.5806 1.0000 31.1935] + + r = [ 4.3032 + 5.4000 + 5.0323] + + S\r = [ 0.2102 + 2.1367 + 0.1388] + + A\b = [-2.3061 + 0.3172 + 0.2102 + 2.1367 + 0.1388] +*/ +// The following two functions create a TripletSparseMatrix and a +// BlockSparseMatrix version of this problem. + +// TripletSparseMatrix version. +LinearLeastSquaresProblem* LinearLeastSquaresProblem1() { + int num_rows = 6; + int num_cols = 5; + + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + TripletSparseMatrix* A = new TripletSparseMatrix(num_rows, + num_cols, + num_rows * num_cols); + problem->b.reset(new double[num_rows]); + problem->D.reset(new double[num_cols]); + problem->num_eliminate_blocks = 2; + + int* rows = A->mutable_rows(); + int* cols = A->mutable_cols(); + double* values = A->mutable_values(); + + int nnz = 0; + + // Row 1 + { + rows[nnz] = 0; + cols[nnz] = 0; + values[nnz++] = 1; + + rows[nnz] = 0; + cols[nnz] = 2; + values[nnz++] = 2; + } + + // Row 2 + { + rows[nnz] = 1; + cols[nnz] = 0; + values[nnz++] = 3; + + rows[nnz] = 1; + cols[nnz] = 3; + values[nnz++] = 4; + } + + // Row 3 + { + rows[nnz] = 2; + cols[nnz] = 1; + values[nnz++] = 5; + + rows[nnz] = 2; + cols[nnz] = 4; + values[nnz++] = 6; + } + + // Row 4 + { + rows[nnz] = 3; + cols[nnz] = 1; + values[nnz++] = 7; + + rows[nnz] = 3; + cols[nnz] = 2; + values[nnz++] = 8; + } + + // Row 5 + { + rows[nnz] = 4; + cols[nnz] = 1; + values[nnz++] = 9; + + rows[nnz] = 4; + cols[nnz] = 2; + values[nnz++] = 1; + } + + // Row 6 + { + rows[nnz] = 5; + cols[nnz] = 2; + values[nnz++] = 1; + + rows[nnz] = 5; + cols[nnz] = 3; + values[nnz++] = 1; + + rows[nnz] = 5; + cols[nnz] = 4; + values[nnz++] = 1; + } + + A->set_num_nonzeros(nnz); + CHECK(A->IsValid()); + + problem->A.reset(A); + + for (int i = 0; i < num_cols; ++i) { + problem->D.get()[i] = 1; + } + + for (int i = 0; i < num_rows; ++i) { + problem->b.get()[i] = i; + } + + return problem; +} + +// BlockSparseMatrix version +LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { + int num_rows = 6; + int num_cols = 5; + + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + + problem->b.reset(new double[num_rows]); + problem->D.reset(new double[num_cols]); + problem->num_eliminate_blocks = 2; + + CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; + scoped_array values(new double[num_rows * num_cols]); + + for (int c = 0; c < num_cols; ++c) { + bs->cols.push_back(Block()); + bs->cols.back().size = 1; + bs->cols.back().position = c; + } + + int nnz = 0; + + // Row 1 + { + values[nnz++] = 1; + values[nnz++] = 2; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 0; + row.cells.push_back(Cell(0, 0)); + row.cells.push_back(Cell(2, 1)); + } + + // Row 2 + { + values[nnz++] = 3; + values[nnz++] = 4; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 1; + row.cells.push_back(Cell(0, 2)); + row.cells.push_back(Cell(3, 3)); + } + + // Row 3 + { + values[nnz++] = 5; + values[nnz++] = 6; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 2; + row.cells.push_back(Cell(1, 4)); + row.cells.push_back(Cell(4, 5)); + } + + // Row 4 + { + values[nnz++] = 7; + values[nnz++] = 8; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 3; + row.cells.push_back(Cell(1, 6)); + row.cells.push_back(Cell(2, 7)); + } + + // Row 5 + { + values[nnz++] = 9; + values[nnz++] = 1; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 4; + row.cells.push_back(Cell(1, 8)); + row.cells.push_back(Cell(2, 9)); + } + + // Row 6 + { + values[nnz++] = 1; + values[nnz++] = 1; + values[nnz++] = 1; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 5; + row.cells.push_back(Cell(2, 10)); + row.cells.push_back(Cell(3, 11)); + row.cells.push_back(Cell(4, 12)); + } + + BlockSparseMatrix* A = new BlockSparseMatrix(bs); + memcpy(A->mutable_values(), values.get(), nnz * sizeof(*A->values())); + + for (int i = 0; i < num_cols; ++i) { + problem->D.get()[i] = 1; + } + + for (int i = 0; i < num_rows; ++i) { + problem->b.get()[i] = i; + } + + problem->A.reset(A); + + return problem; +} + + +/* + A = [1 0 + 3 0 + 0 5 + 0 7 + 0 9 + 0 0] + + b = [0 + 1 + 2 + 3 + 4 + 5] +*/ +// BlockSparseMatrix version +LinearLeastSquaresProblem* LinearLeastSquaresProblem3() { + int num_rows = 5; + int num_cols = 2; + + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + + problem->b.reset(new double[num_rows]); + problem->D.reset(new double[num_cols]); + problem->num_eliminate_blocks = 2; + + CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; + scoped_array values(new double[num_rows * num_cols]); + + for (int c = 0; c < num_cols; ++c) { + bs->cols.push_back(Block()); + bs->cols.back().size = 1; + bs->cols.back().position = c; + } + + int nnz = 0; + + // Row 1 + { + values[nnz++] = 1; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 0; + row.cells.push_back(Cell(0, 0)); + } + + // Row 2 + { + values[nnz++] = 3; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 1; + row.cells.push_back(Cell(0, 1)); + } + + // Row 3 + { + values[nnz++] = 5; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 2; + row.cells.push_back(Cell(1, 2)); + } + + // Row 4 + { + values[nnz++] = 7; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 3; + row.cells.push_back(Cell(1, 3)); + } + + // Row 5 + { + values[nnz++] = 9; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 4; + row.cells.push_back(Cell(1, 4)); + } + + BlockSparseMatrix* A = new BlockSparseMatrix(bs); + memcpy(A->mutable_values(), values.get(), nnz * sizeof(*A->values())); + + for (int i = 0; i < num_cols; ++i) { + problem->D.get()[i] = 1; + } + + for (int i = 0; i < num_rows; ++i) { + problem->b.get()[i] = i; + } + + problem->A.reset(A); + + return problem; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h new file mode 100644 index 00000000000..46a624bd73f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h @@ -0,0 +1,77 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_LINEAR_LEAST_SQUARES_PROBLEMS_H_ +#define CERES_INTERNAL_LINEAR_LEAST_SQUARES_PROBLEMS_H_ + +#include + +#include "ceres/sparse_matrix.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +// Structure defining a linear least squares problem and if possible +// ground truth solutions. To be used by various LinearSolver tests. +struct LinearLeastSquaresProblem { + LinearLeastSquaresProblem() + : A(NULL), b(NULL), D(NULL), num_eliminate_blocks(0), + x(NULL), x_D(NULL) { + } + + scoped_ptr A; + scoped_array b; + scoped_array D; + // If using the schur eliminator then how many of the variable + // blocks are e_type blocks. + int num_eliminate_blocks; + + // Solution to min_x |Ax - b|^2 + scoped_array x; + // Solution to min_x |Ax - b|^2 + |Dx|^2 + scoped_array x_D; +}; + +// Factories for linear least squares problem. +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id); +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile( + const string& filename); + +LinearLeastSquaresProblem* LinearLeastSquaresProblem0(); +LinearLeastSquaresProblem* LinearLeastSquaresProblem1(); +LinearLeastSquaresProblem* LinearLeastSquaresProblem2(); +LinearLeastSquaresProblem* LinearLeastSquaresProblem3(); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LINEAR_LEAST_SQUARES_PROBLEMS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_operator.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_operator.cc new file mode 100644 index 00000000000..4b59fa13009 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_operator.cc @@ -0,0 +1,40 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/linear_operator.h" + +namespace ceres { +namespace internal { + +LinearOperator::~LinearOperator() { +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_operator.h b/extern/libmv/third_party/ceres/internal/ceres/linear_operator.h new file mode 100644 index 00000000000..d5c15cee6a9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_operator.h @@ -0,0 +1,59 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Base classes for access to an linear operator. + +#ifndef CERES_INTERNAL_LINEAR_OPERATOR_H_ +#define CERES_INTERNAL_LINEAR_OPERATOR_H_ + +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +// This is an abstract base class for linear operators. It supports +// access to size information and left and right multiply operators. +class LinearOperator { + public: + virtual ~LinearOperator(); + + // y = y + Ax; + virtual void RightMultiply(const double* x, double* y) const = 0; + // y = y + A'x; + virtual void LeftMultiply(const double* x, double* y) const = 0; + + virtual int num_rows() const = 0; + virtual int num_cols() const = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LINEAR_OPERATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc new file mode 100644 index 00000000000..b2e3941eea1 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc @@ -0,0 +1,87 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/linear_solver.h" + +#include +#include "ceres/cgnr_solver.h" +#include "ceres/dense_qr_solver.h" +#include "ceres/iterative_schur_complement_solver.h" +#include "ceres/schur_complement_solver.h" +#include "ceres/sparse_normal_cholesky_solver.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +LinearSolver::~LinearSolver() { +} + +LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) { + switch (options.type) { + case CGNR: + return new CgnrSolver(options); + + case SPARSE_NORMAL_CHOLESKY: +#ifndef CERES_NO_SUITESPARSE + return new SparseNormalCholeskySolver(options); +#else + LOG(WARNING) << "SPARSE_NORMAL_CHOLESKY is not available. Please " + << "build Ceres with SuiteSparse. Returning NULL."; + return NULL; +#endif // CERES_NO_SUITESPARSE + + case SPARSE_SCHUR: +#ifndef CERES_NO_SUITESPARSE + return new SparseSchurComplementSolver(options); +#else + LOG(WARNING) << "SPARSE_SCHUR is not available. Please " + << "build Ceres with SuiteSparse. Returning NULL."; + return NULL; +#endif // CERES_NO_SUITESPARSE + + case DENSE_SCHUR: + return new DenseSchurComplementSolver(options); + + case ITERATIVE_SCHUR: + return new IterativeSchurComplementSolver(options); + + case DENSE_QR: + return new DenseQRSolver(options); + + default: + LOG(FATAL) << "Unknown linear solver type :" + << options.type; + return NULL; // MSVC doesn't understand that LOG(FATAL) never returns. + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h new file mode 100644 index 00000000000..5860ecc8a77 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h @@ -0,0 +1,291 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Abstract interface for objects solving linear systems of various +// kinds. + +#ifndef CERES_INTERNAL_LINEAR_SOLVER_H_ +#define CERES_INTERNAL_LINEAR_SOLVER_H_ + +#include + +#include +#include "ceres/block_sparse_matrix.h" +#include "ceres/casts.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/dense_sparse_matrix.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class LinearOperator; + +// Abstract base class for objects that implement algorithms for +// solving linear systems +// +// Ax = b +// +// It is expected that a single instance of a LinearSolver object +// maybe used multiple times for solving different linear +// systems. This allows them to cache and reuse information across +// solves if for example the sparsity of the linear system remains +// constant. +// +// Subclasses of LinearSolver use two structs to configure themselves. +// The Options struct configures the LinearSolver object for its +// lifetime. The PerSolveOptions struct is used to specify options for +// a particular Solve call. +class LinearSolver { + public: + struct Options { + Options() + : type(SPARSE_NORMAL_CHOLESKY), + preconditioner_type(JACOBI), + min_num_iterations(1), + max_num_iterations(1), + num_threads(1), + constant_sparsity(false), + num_eliminate_blocks(0), + residual_reset_period(10), + row_block_size(Dynamic), + e_block_size(Dynamic), + f_block_size(Dynamic) { + } + + LinearSolverType type; + + PreconditionerType preconditioner_type; + + // Number of internal iterations that the solver uses. This + // parameter only makes sense for iterative solvers like CG. + int min_num_iterations; + int max_num_iterations; + + // If possible, how many threads can the solver use. + int num_threads; + + // If possible cache and reuse the symbolic factorization across + // multiple calls. + bool constant_sparsity; + + // Eliminate 0 to num_eliminate_blocks - 1 from the Normal + // equations to form a schur complement. Only used by the Schur + // complement based solver. The most common use for this parameter + // is in the case of structure from motion problems where we have + // camera blocks and point blocks. Then setting the + // num_eliminate_blocks to the number of points allows the solver + // to use the Schur complement trick. For more details see the + // description of this parameter in solver.h. + int num_eliminate_blocks; + + // Iterative solvers, e.g. Preconditioned Conjugate Gradients + // maintain a cheap estimate of the residual which may become + // inaccurate over time. Thus for non-zero values of this + // parameter, the solver can be told to recalculate the value of + // the residual using a |b - Ax| evaluation. + int residual_reset_period; + + // If the block sizes in a BlockSparseMatrix are fixed, then in + // some cases the Schur complement based solvers can detect and + // specialize on them. + // + // It is expected that these parameters are set programmatically + // rather than manually. + // + // Please see explicit_schur_complement_solver_impl.h for more + // details. + int row_block_size; + int e_block_size; + int f_block_size; + }; + + // Options for the Solve method. + struct PerSolveOptions { + PerSolveOptions() + : D(NULL), + preconditioner(NULL), + r_tolerance(0.0), + q_tolerance(0.0) { + } + + // This option only makes sense for unsymmetric linear solvers + // that can solve rectangular linear systems. + // + // Given a matrix A, an optional diagonal matrix D as a vector, + // and a vector b, the linear solver will solve for + // + // | A | x = | b | + // | D | | 0 | + // + // If D is null, then it is treated as zero, and the solver returns + // the solution to + // + // A x = b + // + // In either case, x is the vector that solves the following + // optimization problem. + // + // arg min_x ||Ax - b||^2 + ||Dx||^2 + // + // Here A is a matrix of size m x n, with full column rank. If A + // does not have full column rank, the results returned by the + // solver cannot be relied on. D, if it is not null is an array of + // size n. b is an array of size m and x is an array of size n. + double * D; + + // This option only makes sense for iterative solvers. + // + // In general the performance of an iterative linear solver + // depends on the condition number of the matrix A. For example + // the convergence rate of the conjugate gradients algorithm + // is proportional to the square root of the condition number. + // + // One particularly useful technique for improving the + // conditioning of a linear system is to precondition it. In its + // simplest form a preconditioner is a matrix M such that instead + // of solving Ax = b, we solve the linear system AM^{-1} y = b + // instead, where M is such that the condition number k(AM^{-1}) + // is smaller than the conditioner k(A). Given the solution to + // this system, x = M^{-1} y. The iterative solver takes care of + // the mechanics of solving the preconditioned system and + // returning the corrected solution x. The user only needs to + // supply a linear operator. + // + // A null preconditioner is equivalent to an identity matrix being + // used a preconditioner. + LinearOperator* preconditioner; + + + // The following tolerance related options only makes sense for + // iterative solvers. Direct solvers ignore them. + + // Solver terminates when + // + // |Ax - b| <= r_tolerance * |b|. + // + // This is the most commonly used termination criterion for + // iterative solvers. + double r_tolerance; + + // For PSD matrices A, let + // + // Q(x) = x'Ax - 2b'x + // + // be the cost of the quadratic function defined by A and b. Then, + // the solver terminates at iteration i if + // + // i * (Q(x_i) - Q(x_i-1)) / Q(x_i) < q_tolerance. + // + // This termination criterion is more useful when using CG to + // solve the Newton step. This particular convergence test comes + // from Stephen Nash's work on truncated Newton + // methods. References: + // + // 1. Stephen G. Nash & Ariela Sofer, Assessing A Search + // Direction Within A Truncated Newton Method, Operation + // Research Letters 9(1990) 219-221. + // + // 2. Stephen G. Nash, A Survey of Truncated Newton Methods, + // Journal of Computational and Applied Mathematics, + // 124(1-2), 45-59, 2000. + // + double q_tolerance; + }; + + // Summary of a call to the Solve method. We should move away from + // the true/false method for determining solver success. We should + // let the summary object do the talking. + struct Summary { + Summary() + : residual_norm(0.0), + num_iterations(-1), + termination_type(FAILURE) { + } + + double residual_norm; + int num_iterations; + LinearSolverTerminationType termination_type; + }; + + virtual ~LinearSolver(); + + // Solve Ax = b. + virtual Summary Solve(LinearOperator* A, + const double* b, + const PerSolveOptions& per_solve_options, + double* x) = 0; + + static LinearSolver* Create(const Options& options); +}; + +// This templated subclass of LinearSolver serves as a base class for +// other linear solvers that depend on the particular matrix layout of +// the underlying linear operator. For example some linear solvers +// need low level access to the TripletSparseMatrix implementing the +// LinearOperator interface. This class hides those implementation +// details behind a private virtual method, and has the Solve method +// perform the necessary upcasting. +template +class TypedLinearSolver : public LinearSolver { + public: + virtual ~TypedLinearSolver() {} + virtual LinearSolver::Summary Solve( + LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + CHECK_NOTNULL(A); + CHECK_NOTNULL(b); + CHECK_NOTNULL(x); + return SolveImpl(down_cast(A), b, per_solve_options, x); + } + + private: + virtual LinearSolver::Summary SolveImpl( + MatrixType* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) = 0; +}; + +// Linear solvers that depend on acccess to the low level structure of +// a SparseMatrix. +typedef TypedLinearSolver BlockSparseMatrixSolver; // NOLINT +typedef TypedLinearSolver BlockSparseMatrixBaseSolver; // NOLINT +typedef TypedLinearSolver CompressedRowSparseMatrixSolver; // NOLINT +typedef TypedLinearSolver DenseSparseMatrixSolver; // NOLINT +typedef TypedLinearSolver TripletSparseMatrixSolver; // NOLINT + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LINEAR_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc new file mode 100644 index 00000000000..eeae74e3f95 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc @@ -0,0 +1,140 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include +#include "ceres/internal/eigen.h" +#include "ceres/local_parameterization.h" +#include "ceres/rotation.h" + +namespace ceres { + +IdentityParameterization::IdentityParameterization(const int size) + : size_(size) { + CHECK_GT(size, 0); +} + +bool IdentityParameterization::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + VectorRef(x_plus_delta, size_) = + ConstVectorRef(x, size_) + ConstVectorRef(delta, size_); + return true; +} + +bool IdentityParameterization::ComputeJacobian(const double* x, + double* jacobian) const { + MatrixRef(jacobian, size_, size_) = Matrix::Identity(size_, size_); + return true; +} + +SubsetParameterization::SubsetParameterization( + int size, + const vector& constant_parameters) + : local_size_(size - constant_parameters.size()), + constancy_mask_(size, 0) { + CHECK_GT(constant_parameters.size(), 0) + << "The set of constant parameters should contain at least " + << "one element. If you do not wish to hold any parameters " + << "constant, then do not use a SubsetParameterization"; + + vector constant = constant_parameters; + sort(constant.begin(), constant.end()); + CHECK(unique(constant.begin(), constant.end()) == constant.end()) + << "The set of constant parameters cannot contain duplicates"; + CHECK_LT(constant_parameters.size(), size) + << "Number of parameters held constant should be less " + << "than the size of the parameter block. If you wish " + << "to hold the entire parameter block constant, then a " + << "efficient way is to directly mark it as constant " + << "instead of using a LocalParameterization to do so."; + CHECK_GE(*min_element(constant.begin(), constant.end()), 0); + CHECK_LT(*max_element(constant.begin(), constant.end()), size); + + for (int i = 0; i < constant_parameters.size(); ++i) { + constancy_mask_[constant_parameters[i]] = 1; + } +} + +bool SubsetParameterization::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + for (int i = 0, j = 0; i < constancy_mask_.size(); ++i) { + if (constancy_mask_[i]) { + x_plus_delta[i] = x[i]; + } else { + x_plus_delta[i] = x[i] + delta[j++]; + } + } + return true; +} + +bool SubsetParameterization::ComputeJacobian(const double* x, + double* jacobian) const { + MatrixRef m(jacobian, constancy_mask_.size(), local_size_); + m.setZero(); + for (int i = 0, j = 0; i < constancy_mask_.size(); ++i) { + if (!constancy_mask_[i]) { + m(i, j++) = 1.0; + } + } + return true; +} + +bool QuaternionParameterization::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + const double norm_delta = + sqrt(delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]); + if (norm_delta > 0.0) { + const double sin_delta_by_delta = (sin(norm_delta) / norm_delta); + double q_delta[4]; + q_delta[0] = cos(norm_delta); + q_delta[1] = sin_delta_by_delta * delta[0]; + q_delta[2] = sin_delta_by_delta * delta[1]; + q_delta[3] = sin_delta_by_delta * delta[2]; + QuaternionProduct(q_delta, x, x_plus_delta); + } else { + for (int i = 0; i < 4; ++i) { + x_plus_delta[i] = x[i]; + } + } + return true; +} + +bool QuaternionParameterization::ComputeJacobian(const double* x, + double* jacobian) const { + jacobian[0] = -x[1]; jacobian[1] = -x[2]; jacobian[2] = -x[3]; // NOLINT + jacobian[3] = x[0]; jacobian[4] = x[3]; jacobian[5] = -x[2]; // NOLINT + jacobian[6] = -x[3]; jacobian[7] = x[0]; jacobian[8] = x[1]; // NOLINT + jacobian[9] = x[2]; jacobian[10] = -x[1]; jacobian[11] = x[0]; // NOLINT + return true; +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc new file mode 100644 index 00000000000..00b2b184729 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc @@ -0,0 +1,93 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Purpose: See .h file. + +#include "ceres/loss_function.h" + +#include +#include + +namespace ceres { + +void TrivialLoss::Evaluate(double s, double rho[3]) const { + rho[0] = s; + rho[1] = 1; + rho[2] = 0; +} + +void HuberLoss::Evaluate(double s, double rho[3]) const { + if (s > b_) { + // Outlier region. + // 'r' is always positive. + const double r = sqrt(s); + rho[0] = 2 * a_ * r - b_; + rho[1] = a_ / r; + rho[2] = - rho[1] / (2 * s); + } else { + // Inlier region. + rho[0] = s; + rho[1] = 1; + rho[2] = 0; + } +} + +void SoftLOneLoss::Evaluate(double s, double rho[3]) const { + const double sum = 1 + s * c_; + const double tmp = sqrt(sum); + // 'sum' and 'tmp' are always positive, assuming that 's' is. + rho[0] = 2 * b_ * (tmp - 1); + rho[1] = 1 / tmp; + rho[2] = - (c_ * rho[1]) / (2 * sum); +} + +void CauchyLoss::Evaluate(double s, double rho[3]) const { + const double sum = 1 + s * c_; + const double inv = 1 / sum; + // 'sum' and 'inv' are always positive, assuming that 's' is. + rho[0] = b_ * log(sum); + rho[1] = inv; + rho[2] = - c_ * (inv * inv); +} + +void ScaledLoss::Evaluate(double s, double rho[3]) const { + if (rho_.get() == NULL) { + rho[0] = a_ * s; + rho[1] = a_; + rho[2] = 0.0; + } else { + rho_->Evaluate(s, rho); + rho[0] *= a_; + rho[1] *= a_; + rho[2] *= a_; + } +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/map_util.h b/extern/libmv/third_party/ceres/internal/ceres/map_util.h new file mode 100644 index 00000000000..ddf1252f674 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/map_util.h @@ -0,0 +1,129 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Originally by Anton Carver + +#ifndef CERES_INTERNAL_MAP_UTIL_H_ +#define CERES_INTERNAL_MAP_UTIL_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { + +// Perform a lookup in a map or hash_map, assuming that the key exists. +// Crash if it does not. +// +// This is intended as a replacement for operator[] as an rvalue (for reading) +// when the key is guaranteed to exist. +// +// operator[] is discouraged for several reasons: +// * It has a side-effect of inserting missing keys +// * It is not thread-safe (even when it is not inserting, it can still +// choose to resize the underlying storage) +// * It invalidates iterators (when it chooses to resize) +// * It default constructs a value object even if it doesn't need to +// +// This version assumes the key is printable, and includes it in the fatal log +// message. +template +const typename Collection::value_type::second_type& +FindOrDie(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + CHECK(it != collection.end()) << "Map key not found: " << key; + return it->second; +} + +// Perform a lookup in a map or hash_map. +// If the key is present in the map then the value associated with that +// key is returned, otherwise the value passed as a default is returned. +template +const typename Collection::value_type::second_type& +FindWithDefault(const Collection& collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return value; + } + return it->second; +} + +// Insert a new key and value into a map or hash_map. +// If the key is not present in the map the key and value are +// inserted, otherwise nothing happens. True indicates that an insert +// took place, false indicates the key was already present. +template +bool InsertIfNotPresent( + Collection * const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + pair ret = + collection->insert(typename Collection::value_type(key, value)); + return ret.second; +} + +// Perform a lookup in a map or hash_map. +// Same as above but the returned pointer is not const and can be used to change +// the stored value. +template +typename Collection::value_type::second_type* +FindOrNull(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return &it->second; +} + +// Test to see if a set, map, hash_set or hash_map contains a particular key. +// Returns true if the key is in the collection. +template +bool ContainsKey(const Collection& collection, const Key& key) { + typename Collection::const_iterator it = collection.find(key); + return it != collection.end(); +} + +// Inserts a new key/value into a map or hash_map. +// Dies if the key is already present. +template +void InsertOrDie(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + typedef typename Collection::value_type value_type; + CHECK(collection->insert(value_type(key, data)).second) + << "duplicate key: " << key; +} + +} // namespace ceres + +#endif // CERES_INTERNAL_MAP_UTIL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h b/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h new file mode 100644 index 00000000000..b8a3a1a6de6 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h @@ -0,0 +1,40 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A portability header to make optional protocol buffer support less intrusive. + +#ifndef CERES_INTERNAL_MATRIX_PROTO_H_ +#define CERES_INTERNAL_MATRIX_PROTO_H_ + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#include "ceres/matrix.pb.h" +#endif + +#endif // CERES_INTERNAL_MATRIX_PROTO_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h new file mode 100644 index 00000000000..71163a8ea6f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h @@ -0,0 +1,102 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_MINIMIZER_H_ +#define CERES_INTERNAL_MINIMIZER_H_ + +#include +#include "ceres/solver.h" +#include "ceres/iteration_callback.h" + +namespace ceres { +namespace internal { + +class Evaluator; +class LinearSolver; + +// Interface for non-linear least squares solvers. +class Minimizer { + public: + // Options struct to control the behaviour of the Minimizer. Please + // see solver.h for detailed information about the meaning and + // default values of each of these parameters. + struct Options { + explicit Options(const Solver::Options& options) { + max_num_iterations = options.max_num_iterations; + max_solver_time_sec = options.max_solver_time_sec; + gradient_tolerance = options.gradient_tolerance; + parameter_tolerance = options.parameter_tolerance; + function_tolerance = options.function_tolerance; + min_relative_decrease = options.min_relative_decrease; + eta = options.eta; + tau = options.tau; + jacobi_scaling = options.jacobi_scaling; + crash_and_dump_lsqp_on_failure = options.crash_and_dump_lsqp_on_failure; + lsqp_dump_format = options.lsqp_dump_format; + lsqp_iterations_to_dump = options.lsqp_iterations_to_dump; + num_eliminate_blocks = options.num_eliminate_blocks; + logging_type = options.logging_type; + } + + int max_num_iterations; + int max_solver_time_sec; + double gradient_tolerance; + double parameter_tolerance; + double function_tolerance; + double min_relative_decrease; + double eta; + double tau; + bool jacobi_scaling; + bool crash_and_dump_lsqp_on_failure; + string lsqp_dump_format; + vector lsqp_iterations_to_dump; + int num_eliminate_blocks; + LoggingType logging_type; + + // List of callbacks that are executed by the Minimizer at the end + // of each iteration. + // + // Client owns these pointers. + vector callbacks; + }; + + virtual ~Minimizer() {} + virtual void Minimize(const Options& options, + Evaluator* evaluator, + LinearSolver* linear_solver, + const double* initial_parameters, + double* final_parameters, + Solver::Summary* summary) = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_MINIMIZER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/mutex.h b/extern/libmv/third_party/ceres/internal/ceres/mutex.h new file mode 100644 index 00000000000..6514b107041 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/mutex.h @@ -0,0 +1,312 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: Craig Silverstein. +// +// A simple mutex wrapper, supporting locks and read-write locks. +// You should assume the locks are *not* re-entrant. +// +// This class is meant to be internal-only and should be wrapped by an +// internal namespace. Before you use this module, please give the +// name of your internal namespace for this module. Or, if you want +// to expose it, you'll want to move it to the Google namespace. We +// cannot put this class in global namespace because there can be some +// problems when we have multiple versions of Mutex in each shared object. +// +// NOTE: by default, we have #ifdef'ed out the TryLock() method. +// This is for two reasons: +// 1) TryLock() under Windows is a bit annoying (it requires a +// #define to be defined very early). +// 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG +// mode. +// If you need TryLock(), and either these two caveats are not a +// problem for you, or you're willing to work around them, then +// feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs +// in the code below. +// +// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy: +// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html +// Because of that, we might as well use windows locks for +// cygwin. They seem to be more reliable than the cygwin pthreads layer. +// +// TRICKY IMPLEMENTATION NOTE: +// This class is designed to be safe to use during +// dynamic-initialization -- that is, by global constructors that are +// run before main() starts. The issue in this case is that +// dynamic-initialization happens in an unpredictable order, and it +// could be that someone else's dynamic initializer could call a +// function that tries to acquire this mutex -- but that all happens +// before this mutex's constructor has run. (This can happen even if +// the mutex and the function that uses the mutex are in the same .cc +// file.) Basically, because Mutex does non-trivial work in its +// constructor, it's not, in the naive implementation, safe to use +// before dynamic initialization has run on it. +// +// The solution used here is to pair the actual mutex primitive with a +// bool that is set to true when the mutex is dynamically initialized. +// (Before that it's false.) Then we modify all mutex routines to +// look at the bool, and not try to lock/unlock until the bool makes +// it to true (which happens after the Mutex constructor has run.) +// +// This works because before main() starts -- particularly, during +// dynamic initialization -- there are no threads, so a) it's ok that +// the mutex operations are a no-op, since we don't need locking then +// anyway; and b) we can be quite confident our bool won't change +// state between a call to Lock() and a call to Unlock() (that would +// require a global constructor in one translation unit to call Lock() +// and another global constructor in another translation unit to call +// Unlock() later, which is pretty perverse). +// +// That said, it's tricky, and can conceivably fail; it's safest to +// avoid trying to acquire a mutex in a global constructor, if you +// can. One way it can fail is that a really smart compiler might +// initialize the bool to true at static-initialization time (too +// early) rather than at dynamic-initialization time. To discourage +// that, we set is_safe_ to true in code (not the constructor +// colon-initializer) and set it to true via a function that always +// evaluates to true, but that the compiler can't know always +// evaluates to true. This should be good enough. + +#ifndef CERES_INTERNAL_MUTEX_H_ +#define CERES_INTERNAL_MUTEX_H_ + +#if defined(NO_THREADS) + typedef int MutexType; // to keep a lock-count +#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__) +# define WIN32_LEAN_AND_MEAN // We only need minimal includes +# ifdef GMUTEX_TRYLOCK + // We need Windows NT or later for TryEnterCriticalSection(). If you + // don't need that functionality, you can remove these _WIN32_WINNT + // lines, and change TryLock() to assert(0) or something. +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0400 +# endif +# endif +// To avoid macro definition of ERROR. +# define NOGDI +// To avoid macro definition of min/max. +# define NOMINMAX +# include + typedef CRITICAL_SECTION MutexType; +#elif defined(CERES_HAVE_PTHREAD) && defined(CERES_HAVE_RWLOCK) + // Needed for pthread_rwlock_*. If it causes problems, you could take it + // out, but then you'd have to unset CERES_HAVE_RWLOCK (at least on linux -- + // it *does* cause problems for FreeBSD, or MacOSX, but isn't needed for + // locking there.) +# if defined(__linux__) && !defined(_XOPEN_SOURCE) +# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls +# endif +# include + typedef pthread_rwlock_t MutexType; +#elif defined(CERES_HAVE_PTHREAD) +# include + typedef pthread_mutex_t MutexType; +#else +# error Need to implement mutex.h for your architecture, or #define NO_THREADS +#endif + +// We need to include these header files after defining _XOPEN_SOURCE +// as they may define the _XOPEN_SOURCE macro. +#include +#include // for abort() + +namespace ceres { +namespace internal { + +class Mutex { + public: + // Create a Mutex that is not held by anybody. This constructor is + // typically used for Mutexes allocated on the heap or the stack. + // See below for a recommendation for constructing global Mutex + // objects. + inline Mutex(); + + // Destructor + inline ~Mutex(); + + inline void Lock(); // Block if needed until free then acquire exclusively + inline void Unlock(); // Release a lock acquired via Lock() +#ifdef GMUTEX_TRYLOCK + inline bool TryLock(); // If free, Lock() and return true, else return false +#endif + // Note that on systems that don't support read-write locks, these may + // be implemented as synonyms to Lock() and Unlock(). So you can use + // these for efficiency, but don't use them anyplace where being able + // to do shared reads is necessary to avoid deadlock. + inline void ReaderLock(); // Block until free or shared then acquire a share + inline void ReaderUnlock(); // Release a read share of this Mutex + inline void WriterLock() { Lock(); } // Acquire an exclusive lock + inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock() + + // TODO(hamaji): Do nothing, implement correctly. + inline void AssertHeld() {} + + private: + MutexType mutex_; + // We want to make sure that the compiler sets is_safe_ to true only + // when we tell it to, and never makes assumptions is_safe_ is + // always true. volatile is the most reliable way to do that. + volatile bool is_safe_; + + inline void SetIsSafe() { is_safe_ = true; } + + // Catch the error of writing Mutex when intending MutexLock. + Mutex(Mutex* /*ignored*/) {} + // Disallow "evil" constructors + Mutex(const Mutex&); + void operator=(const Mutex&); +}; + +// Now the implementation of Mutex for various systems +#if defined(NO_THREADS) + +// When we don't have threads, we can be either reading or writing, +// but not both. We can have lots of readers at once (in no-threads +// mode, that's most likely to happen in recursive function calls), +// but only one writer. We represent this by having mutex_ be -1 when +// writing and a number > 0 when reading (and 0 when no lock is held). +// +// In debug mode, we assert these invariants, while in non-debug mode +// we do nothing, for efficiency. That's why everything is in an +// assert. + +Mutex::Mutex() : mutex_(0) { } +Mutex::~Mutex() { assert(mutex_ == 0); } +void Mutex::Lock() { assert(--mutex_ == -1); } +void Mutex::Unlock() { assert(mutex_++ == -1); } +#ifdef GMUTEX_TRYLOCK +bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } +#endif +void Mutex::ReaderLock() { assert(++mutex_ > 0); } +void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } + +#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__) + +Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); } +Mutex::~Mutex() { DeleteCriticalSection(&mutex_); } +void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); } +void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); } +#ifdef GMUTEX_TRYLOCK +bool Mutex::TryLock() { return is_safe_ ? + TryEnterCriticalSection(&mutex_) != 0 : true; } +#endif +void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks +void Mutex::ReaderUnlock() { Unlock(); } + +#elif defined(CERES_HAVE_PTHREAD) && defined(CERES_HAVE_RWLOCK) + +#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ + if (is_safe_ && fncall(&mutex_) != 0) abort(); \ +} while (0) + +Mutex::Mutex() { + SetIsSafe(); + if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); +} +Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); } +void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); } +void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } +#ifdef GMUTEX_TRYLOCK +bool Mutex::TryLock() { return is_safe_ ? + pthread_rwlock_trywrlock(&mutex_) == 0 : + true; } +#endif +void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); } +void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } +#undef SAFE_PTHREAD + +#elif defined(CERES_HAVE_PTHREAD) + +#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ + if (is_safe_ && fncall(&mutex_) != 0) abort(); \ +} while (0) + +Mutex::Mutex() { + SetIsSafe(); + if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); +} +Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); } +void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } +void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } +#ifdef GMUTEX_TRYLOCK +bool Mutex::TryLock() { return is_safe_ ? + pthread_mutex_trylock(&mutex_) == 0 : true; } +#endif +void Mutex::ReaderLock() { Lock(); } +void Mutex::ReaderUnlock() { Unlock(); } +#undef SAFE_PTHREAD + +#endif + +// -------------------------------------------------------------------------- +// Some helper classes + +// MutexLock(mu) acquires mu when constructed and releases it when destroyed. +class MutexLock { + public: + explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } + ~MutexLock() { mu_->Unlock(); } + private: + Mutex * const mu_; + // Disallow "evil" constructors + MutexLock(const MutexLock&); + void operator=(const MutexLock&); +}; + +// ReaderMutexLock and WriterMutexLock do the same, for rwlocks +class ReaderMutexLock { + public: + explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } + ~ReaderMutexLock() { mu_->ReaderUnlock(); } + private: + Mutex * const mu_; + // Disallow "evil" constructors + ReaderMutexLock(const ReaderMutexLock&); + void operator=(const ReaderMutexLock&); +}; + +class WriterMutexLock { + public: + explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } + ~WriterMutexLock() { mu_->WriterUnlock(); } + private: + Mutex * const mu_; + // Disallow "evil" constructors + WriterMutexLock(const WriterMutexLock&); + void operator=(const WriterMutexLock&); +}; + +// Catch bug where variable name is omitted, e.g. MutexLock (&mu); +#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) +#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) +#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_MUTEX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc b/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc new file mode 100644 index 00000000000..f30bbc8b46b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc @@ -0,0 +1,67 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/normal_prior.h" + +#include +#include + +#include +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +NormalPrior::NormalPrior(const Matrix& A, const Vector& b) + : A_(A), b_(b) { + CHECK_GT(b_.rows(), 0); + CHECK_GT(A_.rows(), 0); + CHECK_EQ(b_.rows(), A.cols()); + set_num_residuals(A_.rows()); + mutable_parameter_block_sizes()->push_back(b_.rows()); +} + +bool NormalPrior::Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + ConstVectorRef p(parameters[0], parameter_block_sizes()[0]); + VectorRef r(residuals, num_residuals()); + // The following line should read + // r = A_ * (p - b_); + // The extra eval is to get around a bug in the eigen library. + r = A_ * (p - b_).eval(); + if ((jacobians != NULL) && (jacobians[0] != NULL)) { + MatrixRef(jacobians[0], num_residuals(), parameter_block_sizes()[0]) = A_; + } + return true; +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h new file mode 100644 index 00000000000..4bac1a85828 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h @@ -0,0 +1,256 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_PARAMETER_BLOCK_H_ +#define CERES_INTERNAL_PARAMETER_BLOCK_H_ + +#include +#include "ceres/integral_types.h" +#include +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/local_parameterization.h" +#include "ceres/residual_block_utils.h" + +namespace ceres { +namespace internal { + +class ProblemImpl; + +// The parameter block encodes the location of the user's original value, and +// also the "current state" of the parameter. The evaluator uses whatever is in +// the current state of the parameter when evaluating. This is inlined since the +// methods are performance sensitive. +// +// The class is not thread-safe, unless only const methods are called. The +// parameter block may also hold a pointer to a local parameterization; the +// parameter block does not take ownership of this pointer, so the user is +// responsible for the proper disposal of the local parameterization. +class ParameterBlock { + public: + ParameterBlock(double* user_state, int size) { + Init(user_state, size, NULL); + } + ParameterBlock(double* user_state, + int size, + LocalParameterization* local_parameterization) { + Init(user_state, size, local_parameterization); + } + + // The size of the parameter block. + int Size() const { return size_; } + + // Manipulate the parameter state. + bool SetState(const double* x) { + CHECK(x != NULL) + << "Tried to set the state of constant parameter " + << "with user location " << user_state_; + CHECK(!is_constant_) + << "Tried to set the state of constant parameter " + << "with user location " << user_state_; + + state_ = x; + return UpdateLocalParameterizationJacobian(); + } + + // Copy the current parameter state out to x. This is "GetState()" rather than + // simply "state()" since it is actively copying the data into the passed + // pointer. + void GetState(double *x) const { + if (x != state_) { + memcpy(x, state_, sizeof(*state_) * size_); + } + } + + // Direct pointers to the current state. + const double* state() const { return state_; } + const double* user_state() const { return user_state_; } + double* mutable_user_state() { return user_state_; } + LocalParameterization* local_parameterization() const { + return local_parameterization_; + } + LocalParameterization* mutable_local_parameterization() { + return local_parameterization_; + } + + // Set this parameter block to vary or not. + void SetConstant() { is_constant_ = true; } + void SetVarying() { is_constant_ = false; } + bool IsConstant() const { return is_constant_; } + + // This parameter block's index in an array. + int index() const { return index_; } + void set_index(int index) { index_ = index; } + + // This parameter offset inside a larger state vector. + int state_offset() const { return state_offset_; } + void set_state_offset(int state_offset) { state_offset_ = state_offset; } + + // This parameter offset inside a larger delta vector. + int delta_offset() const { return delta_offset_; } + void set_delta_offset(int delta_offset) { delta_offset_ = delta_offset; } + + // Methods relating to the parameter block's parameterization. + + // The local to global jacobian. Returns NULL if there is no local + // parameterization for this parameter block. The returned matrix is row-major + // and has Size() rows and LocalSize() columns. + const double* LocalParameterizationJacobian() const { + return local_parameterization_jacobian_.get(); + } + + int LocalSize() const { + return (local_parameterization_ == NULL) + ? size_ + : local_parameterization_->LocalSize(); + } + + // Set the parameterization. The parameterization can be set exactly once; + // multiple calls to set the parameterization to different values will crash. + // It is an error to pass NULL for the parameterization. The parameter block + // does not take ownership of the parameterization. + void SetParameterization(LocalParameterization* new_parameterization) { + CHECK(new_parameterization != NULL) << "NULL parameterization invalid."; + CHECK(new_parameterization->GlobalSize() == size_) + << "Invalid parameterization for parameter block. The parameter block " + << "has size " << size_ << " while the parameterization has a global " + << "size of " << new_parameterization->GlobalSize() << ". Did you " + << "accidentally use the wrong parameter block or parameterization?"; + if (new_parameterization != local_parameterization_) { + CHECK(local_parameterization_ == NULL) + << "Can't re-set the local parameterization; it leads to " + << "ambiguous ownership."; + local_parameterization_ = new_parameterization; + local_parameterization_jacobian_.reset( + new double[local_parameterization_->GlobalSize() * + local_parameterization_->LocalSize()]); + CHECK(UpdateLocalParameterizationJacobian()) + "Local parameterization Jacobian computation failed" + "for x: " << ConstVectorRef(state_, Size()).transpose(); + } else { + // Ignore the case that the parameterizations match. + } + } + + // Generalization of the addition operation. This is the same as + // LocalParameterization::Plus() but uses the parameter's current state + // instead of operating on a passed in pointer. + bool Plus(const double *x, const double* delta, double* x_plus_delta) { + if (local_parameterization_ == NULL) { + VectorRef(x_plus_delta, size_) = ConstVectorRef(x, size_) + + ConstVectorRef(delta, size_); + return true; + } + return local_parameterization_->Plus(x, delta, x_plus_delta); + } + + private: + void Init(double* user_state, + int size, + LocalParameterization* local_parameterization) { + user_state_ = user_state; + size_ = size; + is_constant_ = false; + state_ = user_state_; + + local_parameterization_ = NULL; + if (local_parameterization != NULL) { + SetParameterization(local_parameterization); + } + + index_ = -1; + state_offset_ = -1; + delta_offset_ = -1; + } + + bool UpdateLocalParameterizationJacobian() { + if (local_parameterization_ == NULL) { + return true; + } + + // Update the local to global Jacobian. In some cases this is + // wasted effort; if this is a bottleneck, we will find a solution + // at that time. + + const int jacobian_size = Size() * LocalSize(); + InvalidateArray(jacobian_size, + local_parameterization_jacobian_.get()); + if (!local_parameterization_->ComputeJacobian( + state_, + local_parameterization_jacobian_.get())) { + LOG(WARNING) << "Local parameterization Jacobian computation failed" + "for x: " << ConstVectorRef(state_, Size()).transpose(); + return false; + } + + if (!IsArrayValid(jacobian_size, local_parameterization_jacobian_.get())) { + LOG(WARNING) << "Local parameterization Jacobian computation returned" + << "an invalid matrix for x: " + << ConstVectorRef(state_, Size()).transpose() + << "\n Jacobian matrix : " + << ConstMatrixRef(local_parameterization_jacobian_.get(), + Size(), + LocalSize()); + return false; + } + return true; + } + + double* user_state_; + int size_; + bool is_constant_; + LocalParameterization* local_parameterization_; + + // The "state" of the parameter. These fields are only needed while the + // solver is running. While at first glance using mutable is a bad idea, this + // ends up simplifying the internals of Ceres enough to justify the potential + // pitfalls of using "mutable." + mutable const double* state_; + mutable scoped_array local_parameterization_jacobian_; + + // The index of the parameter. This is used by various other parts of Ceres to + // permit switching from a ParameterBlock* to an index in another array. + int32 index_; + + // The offset of this parameter block inside a larger state vector. + int32 state_offset_; + + // The offset of this parameter block inside a larger delta vector. + int32 delta_offset_; + + // Necessary so ProblemImpl can clean up the parameterizations. + friend class ProblemImpl; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PARAMETER_BLOCK_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc new file mode 100644 index 00000000000..fcf8fd53aed --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc @@ -0,0 +1,315 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 10 + +#include "ceres/partitioned_matrix_view.h" + +#include +#include +#include +#include +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +PartitionedMatrixView::PartitionedMatrixView( + const BlockSparseMatrixBase& matrix, + int num_col_blocks_a) + : matrix_(matrix), + num_col_blocks_e_(num_col_blocks_a) { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + CHECK_NOTNULL(bs); + + num_col_blocks_f_ = bs->cols.size() - num_col_blocks_a; + + // Compute the number of row blocks in E. The number of row blocks + // in E maybe less than the number of row blocks in the input matrix + // as some of the row blocks at the bottom may not have any + // e_blocks. For a definition of what an e_block is, please see + // explicit_schur_complement_solver.h + num_row_blocks_e_ = 0; + for (int r = 0; r < bs->rows.size(); ++r) { + const vector& cells = bs->rows[r].cells; + if (cells[0].block_id < num_col_blocks_a) { + ++num_row_blocks_e_; + } + } + + // Compute the number of columns in E and F. + num_cols_e_ = 0; + num_cols_f_ = 0; + + for (int c = 0; c < bs->cols.size(); ++c) { + const Block& block = bs->cols[c]; + if (c < num_col_blocks_a) { + num_cols_e_ += block.size; + } else { + num_cols_f_ += block.size; + } + } + + CHECK_EQ(num_cols_e_ + num_cols_f_, matrix_.num_cols()); +} + +PartitionedMatrixView::~PartitionedMatrixView() { +} + +// The next four methods don't seem to be particularly cache +// friendly. This is an artifact of how the BlockStructure of the +// input matrix is constructed. These methods will benefit from +// multithreading as well as improved data layout. + +void PartitionedMatrixView::RightMultiplyE(const double* x, double* y) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + + // Iterate over the first num_row_blocks_e_ row blocks, and multiply + // by the first cell in each row block. + for (int r = 0; r < num_row_blocks_e_; ++r) { + const double* row_values = matrix_.RowBlockValues(r); + const Cell& cell = bs->rows[r].cells[0]; + const int row_block_pos = bs->rows[r].block.position; + const int row_block_size = bs->rows[r].block.size; + const int col_block_id = cell.block_id; + const int col_block_pos = bs->cols[col_block_id].position; + const int col_block_size = bs->cols[col_block_id].size; + + ConstVectorRef xref(x + col_block_pos, col_block_size); + VectorRef yref(y + row_block_pos, row_block_size); + ConstMatrixRef m(row_values + cell.position, + row_block_size, + col_block_size); + yref += m.lazyProduct(xref); + } +} + +void PartitionedMatrixView::RightMultiplyF(const double* x, double* y) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + + // Iterate over row blocks, and if the row block is in E, then + // multiply by all the cells except the first one which is of type + // E. If the row block is not in E (i.e its in the bottom + // num_row_blocks - num_row_blocks_e row blocks), then all the cells + // are of type F and multiply by them all. + for (int r = 0; r < bs->rows.size(); ++r) { + const int row_block_pos = bs->rows[r].block.position; + const int row_block_size = bs->rows[r].block.size; + VectorRef yref(y + row_block_pos, row_block_size); + const vector& cells = bs->rows[r].cells; + for (int c = (r < num_row_blocks_e_) ? 1 : 0; c < cells.size(); ++c) { + const double* row_values = matrix_.RowBlockValues(r); + const int col_block_id = cells[c].block_id; + const int col_block_pos = bs->cols[col_block_id].position; + const int col_block_size = bs->cols[col_block_id].size; + + ConstVectorRef xref(x + col_block_pos - num_cols_e(), + col_block_size); + ConstMatrixRef m(row_values + cells[c].position, + row_block_size, + col_block_size); + yref += m.lazyProduct(xref); + } + } +} + +void PartitionedMatrixView::LeftMultiplyE(const double* x, double* y) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + + // Iterate over the first num_row_blocks_e_ row blocks, and multiply + // by the first cell in each row block. + for (int r = 0; r < num_row_blocks_e_; ++r) { + const Cell& cell = bs->rows[r].cells[0]; + const double* row_values = matrix_.RowBlockValues(r); + const int row_block_pos = bs->rows[r].block.position; + const int row_block_size = bs->rows[r].block.size; + const int col_block_id = cell.block_id; + const int col_block_pos = bs->cols[col_block_id].position; + const int col_block_size = bs->cols[col_block_id].size; + + ConstVectorRef xref(x + row_block_pos, row_block_size); + VectorRef yref(y + col_block_pos, col_block_size); + ConstMatrixRef m(row_values + cell.position, + row_block_size, + col_block_size); + yref += m.transpose().lazyProduct(xref); + } +} + +void PartitionedMatrixView::LeftMultiplyF(const double* x, double* y) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + + // Iterate over row blocks, and if the row block is in E, then + // multiply by all the cells except the first one which is of type + // E. If the row block is not in E (i.e its in the bottom + // num_row_blocks - num_row_blocks_e row blocks), then all the cells + // are of type F and multiply by them all. + for (int r = 0; r < bs->rows.size(); ++r) { + const int row_block_pos = bs->rows[r].block.position; + const int row_block_size = bs->rows[r].block.size; + ConstVectorRef xref(x + row_block_pos, row_block_size); + const vector& cells = bs->rows[r].cells; + for (int c = (r < num_row_blocks_e_) ? 1 : 0; c < cells.size(); ++c) { + const double* row_values = matrix_.RowBlockValues(r); + const int col_block_id = cells[c].block_id; + const int col_block_pos = bs->cols[col_block_id].position; + const int col_block_size = bs->cols[col_block_id].size; + + VectorRef yref(y + col_block_pos - num_cols_e(), col_block_size); + ConstMatrixRef m(row_values + cells[c].position, + row_block_size, + col_block_size); + yref += m.transpose().lazyProduct(xref); + } + } +} + +// Given a range of columns blocks of a matrix m, compute the block +// structure of the block diagonal of the matrix m(:, +// start_col_block:end_col_block)'m(:, start_col_block:end_col_block) +// and return a BlockSparseMatrix with the this block structure. The +// caller owns the result. +BlockSparseMatrix* PartitionedMatrixView::CreateBlockDiagonalMatrixLayout( + int start_col_block, int end_col_block) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + CompressedRowBlockStructure* block_diagonal_structure = + new CompressedRowBlockStructure; + + int block_position = 0; + int diagonal_cell_position = 0; + + // Iterate over the column blocks, creating a new diagonal block for + // each column block. + for (int c = start_col_block; c < end_col_block; ++c) { + const Block& block = bs->cols[c]; + block_diagonal_structure->cols.push_back(Block()); + Block& diagonal_block = block_diagonal_structure->cols.back(); + diagonal_block.size = block.size; + diagonal_block.position = block_position; + + block_diagonal_structure->rows.push_back(CompressedRow()); + CompressedRow& row = block_diagonal_structure->rows.back(); + row.block = diagonal_block; + + row.cells.push_back(Cell()); + Cell& cell = row.cells.back(); + cell.block_id = c - start_col_block; + cell.position = diagonal_cell_position; + + block_position += block.size; + diagonal_cell_position += block.size * block.size; + } + + // Build a BlockSparseMatrix with the just computed block + // structure. + return new BlockSparseMatrix(block_diagonal_structure); +} + +BlockSparseMatrix* PartitionedMatrixView::CreateBlockDiagonalEtE() const { + BlockSparseMatrix* block_diagonal = + CreateBlockDiagonalMatrixLayout(0, num_col_blocks_e_); + UpdateBlockDiagonalEtE(block_diagonal); + return block_diagonal; +} + +BlockSparseMatrix* PartitionedMatrixView::CreateBlockDiagonalFtF() const { + BlockSparseMatrix* block_diagonal = + CreateBlockDiagonalMatrixLayout( + num_col_blocks_e_, num_col_blocks_e_ + num_col_blocks_f_); + UpdateBlockDiagonalFtF(block_diagonal); + return block_diagonal; +} + +// Similar to the code in RightMultiplyE, except instead of the matrix +// vector multiply its an outer product. +// +// block_diagonal = block_diagonal(E'E) +void PartitionedMatrixView::UpdateBlockDiagonalEtE( + BlockSparseMatrix* block_diagonal) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + const CompressedRowBlockStructure* block_diagonal_structure = + block_diagonal->block_structure(); + + block_diagonal->SetZero(); + + for (int r = 0; r < num_row_blocks_e_ ; ++r) { + const double* row_values = matrix_.RowBlockValues(r); + const Cell& cell = bs->rows[r].cells[0]; + const int row_block_size = bs->rows[r].block.size; + const int block_id = cell.block_id; + const int col_block_size = bs->cols[block_id].size; + ConstMatrixRef m(row_values + cell.position, + row_block_size, + col_block_size); + + const int cell_position = + block_diagonal_structure->rows[block_id].cells[0].position; + + MatrixRef(block_diagonal->mutable_values() + cell_position, + col_block_size, col_block_size).noalias() += m.transpose() * m; + } +} + +// Similar to the code in RightMultiplyF, except instead of the matrix +// vector multiply its an outer product. +// +// block_diagonal = block_diagonal(F'F) +// +void PartitionedMatrixView::UpdateBlockDiagonalFtF( + BlockSparseMatrix* block_diagonal) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + const CompressedRowBlockStructure* block_diagonal_structure = + block_diagonal->block_structure(); + + block_diagonal->SetZero(); + for (int r = 0; r < bs->rows.size(); ++r) { + const int row_block_size = bs->rows[r].block.size; + const vector& cells = bs->rows[r].cells; + const double* row_values = matrix_.RowBlockValues(r); + for (int c = (r < num_row_blocks_e_) ? 1 : 0; c < cells.size(); ++c) { + const int col_block_id = cells[c].block_id; + const int col_block_size = bs->cols[col_block_id].size; + ConstMatrixRef m(row_values + cells[c].position, + row_block_size, + col_block_size); + const int diagonal_block_id = col_block_id - num_col_blocks_e_; + const int cell_position = + block_diagonal_structure->rows[diagonal_block_id].cells[0].position; + + MatrixRef(block_diagonal->mutable_values() + cell_position, + col_block_size, col_block_size).noalias() += m.transpose() * m; + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h new file mode 100644 index 00000000000..cfe4de5b436 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h @@ -0,0 +1,121 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// For generalized bi-partite Jacobian matrices that arise in +// Structure from Motion related problems, it is sometimes useful to +// have access to the two parts of the matrix as linear operators +// themselves. This class provides that functionality. + +#ifndef CERES_INTERNAL_PARTITIONED_MATRIX_VIEW_H_ +#define CERES_INTERNAL_PARTITIONED_MATRIX_VIEW_H_ + +#include "ceres/block_sparse_matrix.h" + +namespace ceres { +namespace internal { + +// Given generalized bi-partite matrix A = [E F], with the same block +// structure as required by the Schur complement based solver, found +// in explicit_schur_complement_solver.h, provide access to the +// matrices E and F and their outer products E'E and F'F with +// themselves. +// +// Lack of BlockStructure object will result in a crash and if the +// block structure of the matrix does not satisfy the requirements of +// the Schur complement solver it will result in unpredictable and +// wrong output. +// +// This class lives in the internal name space as its a utility class +// to be used by the IterativeSchurComplementSolver class, found in +// iterative_schur_complement_solver.h, and is not meant for general +// consumption. +class PartitionedMatrixView { + public: + // matrix = [E F], where the matrix E contains the first + // num_col_blocks_a column blocks. + PartitionedMatrixView(const BlockSparseMatrixBase& matrix, + int num_col_blocks_a); + ~PartitionedMatrixView(); + + // y += E'x + void LeftMultiplyE(const double* x, double* y) const; + + // y += F'x + void LeftMultiplyF(const double* x, double* y) const; + + // y += Ex + void RightMultiplyE(const double* x, double* y) const; + + // y += Fx + void RightMultiplyF(const double* x, double* y) const; + + // Create and return the block diagonal of the matrix E'E. + BlockSparseMatrix* CreateBlockDiagonalEtE() const; + + // Create and return the block diagonal of the matrix F'F. + BlockSparseMatrix* CreateBlockDiagonalFtF() const; + + // Compute the block diagonal of the matrix E'E and store it in + // block_diagonal. The matrix block_diagonal is expected to have a + // BlockStructure (preferably created using + // CreateBlockDiagonalMatrixEtE) which is has the same structure as + // the block diagonal of E'E. + void UpdateBlockDiagonalEtE(BlockSparseMatrix* block_diagonal) const; + + // Compute the block diagonal of the matrix F'F and store it in + // block_diagonal. The matrix block_diagonal is expected to have a + // BlockStructure (preferably created using + // CreateBlockDiagonalMatrixFtF) which is has the same structure as + // the block diagonal of F'F. + void UpdateBlockDiagonalFtF(BlockSparseMatrix* block_diagonal) const; + + int num_col_blocks_e() const { return num_col_blocks_e_; } + int num_col_blocks_f() const { return num_col_blocks_f_; } + int num_cols_e() const { return num_cols_e_; } + int num_cols_f() const { return num_cols_f_; } + int num_rows() const { return matrix_.num_rows(); } + int num_cols() const { return matrix_.num_cols(); } + + private: + BlockSparseMatrix* CreateBlockDiagonalMatrixLayout(int start_col_block, + int end_col_block) const; + + const BlockSparseMatrixBase& matrix_; + int num_row_blocks_e_; + int num_col_blocks_e_; + int num_col_blocks_f_; + int num_cols_e_; + int num_cols_f_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PARTITIONED_MATRIX_VIEW_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem.cc b/extern/libmv/third_party/ceres/internal/ceres/problem.cc new file mode 100644 index 00000000000..b8c25d9db84 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/problem.cc @@ -0,0 +1,149 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) + +#include "ceres/problem.h" + +#include +#include "ceres/problem_impl.h" + +namespace ceres { + +class ResidualBlock; + +Problem::Problem() : problem_impl_(new internal::ProblemImpl) {} +Problem::Problem(const Problem::Options& options) + : problem_impl_(new internal::ProblemImpl(options)) {} +Problem::~Problem() {} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + const vector& parameter_blocks) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + parameter_blocks); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1, x2); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1, x2, x3); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3, double* x4) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1, x2, x3, x4); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3, double* x4, double* x5) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1, x2, x3, x4, x5); +} + +void Problem::AddParameterBlock(double* values, int size) { + problem_impl_->AddParameterBlock(values, size); +} + +void Problem::AddParameterBlock(double* values, + int size, + LocalParameterization* local_parameterization) { + problem_impl_->AddParameterBlock(values, size, local_parameterization); +} + +void Problem::SetParameterBlockConstant(double* values) { + problem_impl_->SetParameterBlockConstant(values); +} + +void Problem::SetParameterBlockVariable(double* values) { + problem_impl_->SetParameterBlockVariable(values); +} + +void Problem::SetParameterization( + double* values, + LocalParameterization* local_parameterization) { + problem_impl_->SetParameterization(values, local_parameterization); +} + +int Problem::NumParameterBlocks() const { + return problem_impl_->NumParameterBlocks(); +} + +int Problem::NumParameters() const { + return problem_impl_->NumParameters(); +} + +int Problem::NumResidualBlocks() const { + return problem_impl_->NumResidualBlocks(); +} + +int Problem::NumResiduals() const { + return problem_impl_->NumResiduals(); +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc new file mode 100644 index 00000000000..68242477d6f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc @@ -0,0 +1,359 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) + +#include "ceres/problem_impl.h" + +#include +#include +#include +#include +#include +#include + +#include +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/stl_util.h" +#include "ceres/map_util.h" +#include "ceres/stringprintf.h" +#include "ceres/cost_function.h" +#include "ceres/loss_function.h" + +namespace ceres { +namespace internal { + +typedef map ParameterMap; + +// Returns true if two regions of memory, a and b, with sizes size_a and size_b +// respectively, overlap. +static bool RegionsAlias(const double* a, int size_a, + const double* b, int size_b) { + return (a < b) ? b < (a + size_a) + : a < (b + size_b); +} + +static void CheckForNoAliasing(double* existing_block, + int existing_block_size, + double* new_block, + int new_block_size) { + CHECK(!RegionsAlias(existing_block, existing_block_size, + new_block, new_block_size)) + << "Aliasing detected between existing parameter block at memory " + << "location " << existing_block + << " and has size " << existing_block_size << " with new parameter " + << "block that has memory adderss " << new_block << " and would have " + << "size " << new_block_size << "."; +} + +static ParameterBlock* InternalAddParameterBlock( + double* values, + int size, + ParameterMap* parameter_map, + vector* parameter_blocks) { + CHECK(values) << "Null pointer passed to AddParameterBlock for a parameter " + << "with size " << size; + + // Ignore the request if there is a block for the given pointer already. + ParameterMap::iterator it = parameter_map->find(values); + if (it != parameter_map->end()) { + int existing_size = it->second->Size(); + CHECK(size == existing_size) + << "Tried adding a parameter block with the same double pointer, " + << values << ", twice, but with different block sizes. Original " + << "size was " << existing_size << " but new size is " + << size; + return it->second; + } + // Before adding the parameter block, also check that it doesn't alias any + // other parameter blocks. + if (!parameter_map->empty()) { + ParameterMap::iterator lb = parameter_map->lower_bound(values); + + // If lb is not the first block, check the previous block for aliasing. + if (lb != parameter_map->begin()) { + ParameterMap::iterator previous = lb; + --previous; + CheckForNoAliasing(previous->first, + previous->second->Size(), + values, + size); + } + + // If lb is not off the end, check lb for aliasing. + if (lb != parameter_map->end()) { + CheckForNoAliasing(lb->first, + lb->second->Size(), + values, + size); + } + } + ParameterBlock* new_parameter_block = new ParameterBlock(values, size); + (*parameter_map)[values] = new_parameter_block; + parameter_blocks->push_back(new_parameter_block); + return new_parameter_block; +} + +ProblemImpl::ProblemImpl() : program_(new internal::Program) {} +ProblemImpl::ProblemImpl(const Problem::Options& options) + : options_(options), + program_(new internal::Program) {} + +ProblemImpl::~ProblemImpl() { + // Collect the unique cost/loss functions and delete the residuals. + set cost_functions; + set loss_functions; + for (int i = 0; i < program_->residual_blocks_.size(); ++i) { + ResidualBlock* residual_block = program_->residual_blocks_[i]; + + // The const casts here are legit, since ResidualBlock holds these + // pointers as const pointers but we have ownership of them and + // have the right to destroy them when the destructor is called. + if (options_.cost_function_ownership == TAKE_OWNERSHIP) { + cost_functions.insert( + const_cast(residual_block->cost_function())); + } + if (options_.loss_function_ownership == TAKE_OWNERSHIP) { + loss_functions.insert( + const_cast(residual_block->loss_function())); + } + + delete residual_block; + } + + // Collect the unique parameterizations and delete the parameters. + set local_parameterizations; + for (int i = 0; i < program_->parameter_blocks_.size(); ++i) { + ParameterBlock* parameter_block = program_->parameter_blocks_[i]; + + if (options_.local_parameterization_ownership == TAKE_OWNERSHIP) { + local_parameterizations.insert(parameter_block->local_parameterization_); + } + + delete parameter_block; + } + + // Delete the owned cost/loss functions and parameterizations. + STLDeleteContainerPointers(local_parameterizations.begin(), + local_parameterizations.end()); + STLDeleteContainerPointers(cost_functions.begin(), + cost_functions.end()); + STLDeleteContainerPointers(loss_functions.begin(), + loss_functions.end()); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + const vector& parameter_blocks) { + CHECK_NOTNULL(cost_function); + CHECK_EQ(parameter_blocks.size(), + cost_function->parameter_block_sizes().size()); + + // Check the sizes match. + const vector& parameter_block_sizes = + cost_function->parameter_block_sizes(); + CHECK_EQ(parameter_block_sizes.size(), parameter_blocks.size()) + << "Number of blocks input is different than the number of blocks " + << "that the cost function expects."; + + // Check for duplicate parameter blocks. + vector sorted_parameter_blocks(parameter_blocks); + sort(sorted_parameter_blocks.begin(), sorted_parameter_blocks.end()); + vector::const_iterator duplicate_items = + unique(sorted_parameter_blocks.begin(), + sorted_parameter_blocks.end()); + if (duplicate_items != sorted_parameter_blocks.end()) { + string blocks; + for (int i = 0; i < parameter_blocks.size(); ++i) { + blocks += internal::StringPrintf(" %p ", parameter_blocks[i]); + } + + LOG(FATAL) << "Duplicate parameter blocks in a residual parameter " + << "are not allowed. Parameter block pointers: [" + << blocks << "]"; + } + + // Add parameter blocks and convert the double*'s to parameter blocks. + vector parameter_block_ptrs(parameter_blocks.size()); + for (int i = 0; i < parameter_blocks.size(); ++i) { + parameter_block_ptrs[i] = + InternalAddParameterBlock(parameter_blocks[i], + parameter_block_sizes[i], + ¶meter_block_map_, + &program_->parameter_blocks_); + } + + // Check that the block sizes match the block sizes expected by the + // cost_function. + for (int i = 0; i < parameter_block_ptrs.size(); ++i) { + CHECK_EQ(cost_function->parameter_block_sizes()[i], + parameter_block_ptrs[i]->Size()) + << "The cost function expects parameter block " << i + << " of size " << cost_function->parameter_block_sizes()[i] + << " but was given a block of size " + << parameter_block_ptrs[i]->Size(); + } + + ResidualBlock* new_residual_block = + new ResidualBlock(cost_function, + loss_function, + parameter_block_ptrs); + program_->residual_blocks_.push_back(new_residual_block); + return new_residual_block; +} + +// Unfortunately, macros don't help much to reduce this code, and var args don't +// work because of the ambiguous case that there is no loss function. +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0) { + vector residual_parameters; + residual_parameters.push_back(x0); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + residual_parameters.push_back(x2); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + residual_parameters.push_back(x2); + residual_parameters.push_back(x3); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3, double* x4) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + residual_parameters.push_back(x2); + residual_parameters.push_back(x3); + residual_parameters.push_back(x4); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3, double* x4, double* x5) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + residual_parameters.push_back(x2); + residual_parameters.push_back(x3); + residual_parameters.push_back(x4); + residual_parameters.push_back(x5); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + + +void ProblemImpl::AddParameterBlock(double* values, int size) { + InternalAddParameterBlock(values, + size, + ¶meter_block_map_, + &program_->parameter_blocks_); +} + +void ProblemImpl::AddParameterBlock( + double* values, + int size, + LocalParameterization* local_parameterization) { + ParameterBlock* parameter_block = + InternalAddParameterBlock(values, + size, + ¶meter_block_map_, + &program_->parameter_blocks_); + if (local_parameterization != NULL) { + parameter_block->SetParameterization(local_parameterization); + } +} + +void ProblemImpl::SetParameterBlockConstant(double* values) { + FindOrDie(parameter_block_map_, values)->SetConstant(); +} + +void ProblemImpl::SetParameterBlockVariable(double* values) { + FindOrDie(parameter_block_map_, values)->SetVarying(); +} + +void ProblemImpl::SetParameterization( + double* values, + LocalParameterization* local_parameterization) { + FindOrDie(parameter_block_map_, values) + ->SetParameterization(local_parameterization); +} + +int ProblemImpl::NumParameterBlocks() const { + return program_->NumParameterBlocks(); +} + +int ProblemImpl::NumParameters() const { + return program_->NumParameters(); +} + +int ProblemImpl::NumResidualBlocks() const { + return program_->NumResidualBlocks(); +} + +int ProblemImpl::NumResiduals() const { + return program_->NumResiduals(); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h new file mode 100644 index 00000000000..523860e652a --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h @@ -0,0 +1,127 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// This is the implementation of the public Problem API. The pointer to +// implementation (PIMPL) idiom makes it possible for Ceres internal code to +// refer to the private data members without needing to exposing it to the +// world. An alternative to PIMPL is to have a factory which returns instances +// of a virtual base class; while that approach would work, it requires clients +// to always put a Problem object into a scoped pointer; this needlessly muddies +// client code for little benefit. Therefore, the PIMPL comprise was chosen. + +#ifndef CERES_PUBLIC_PROBLEM_IMPL_H_ +#define CERES_PUBLIC_PROBLEM_IMPL_H_ + +#include +#include + +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/problem.h" +#include "ceres/types.h" + +namespace ceres { + +class CostFunction; +class LossFunction; +class LocalParameterization; + +namespace internal { + +class Program; +class ResidualBlock; + +class ProblemImpl { + public: + typedef map ParameterMap; + + ProblemImpl(); + explicit ProblemImpl(const Problem::Options& options); + + ~ProblemImpl(); + + // See the public problem.h file for description of these methods. + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + const vector& parameter_blocks); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3, double* x4); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3, double* x4, double* x5); + void AddParameterBlock(double* values, int size); + void AddParameterBlock(double* values, + int size, + LocalParameterization* local_parameterization); + void SetParameterBlockConstant(double* values); + void SetParameterBlockVariable(double* values); + void SetParameterization(double* values, + LocalParameterization* local_parameterization); + int NumParameterBlocks() const; + int NumParameters() const; + int NumResidualBlocks() const; + int NumResiduals() const; + + const Program& program() const { return *program_; } + Program* mutable_program() { return program_.get(); } + + const ParameterMap& parameter_map() const { return parameter_block_map_; } + + private: + const Problem::Options options_; + + // The mapping from user pointers to parameter blocks. + map parameter_block_map_; + + internal::scoped_ptr program_; + DISALLOW_COPY_AND_ASSIGN(ProblemImpl); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_PROBLEM_IMPL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.cc b/extern/libmv/third_party/ceres/internal/ceres/program.cc new file mode 100644 index 00000000000..444b1020253 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/program.cc @@ -0,0 +1,233 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/program.h" + +#include +#include +#include "ceres/parameter_block.h" +#include "ceres/residual_block.h" +#include "ceres/stl_util.h" +#include "ceres/map_util.h" +#include "ceres/problem.h" +#include "ceres/cost_function.h" +#include "ceres/loss_function.h" +#include "ceres/local_parameterization.h" + +namespace ceres { +namespace internal { + +Program::Program() {} + +Program::Program(const Program& program) + : parameter_blocks_(program.parameter_blocks_), + residual_blocks_(program.residual_blocks_) { +} + +const vector& Program::parameter_blocks() const { + return parameter_blocks_; +} + +const vector& Program::residual_blocks() const { + return residual_blocks_; +} + +vector* Program::mutable_parameter_blocks() { + return ¶meter_blocks_; +} + +vector* Program::mutable_residual_blocks() { + return &residual_blocks_; +} + +bool Program::StateVectorToParameterBlocks(const double *state) { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + if (!parameter_blocks_[i]->SetState(state)) { + return false; + } + state += parameter_blocks_[i]->Size(); + } + return true; +} + +void Program::ParameterBlocksToStateVector(double *state) const { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + parameter_blocks_[i]->GetState(state); + state += parameter_blocks_[i]->Size(); + } +} + +void Program::CopyParameterBlockStateToUserState() { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + parameter_blocks_[i]->GetState( + parameter_blocks_[i]->mutable_user_state()); + } +} + +bool Program::Plus(const double* state, + const double* delta, + double* state_plus_delta) const { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + if (!parameter_blocks_[i]->Plus(state, delta, state_plus_delta)) { + return false; + } + state += parameter_blocks_[i]->Size(); + delta += parameter_blocks_[i]->LocalSize(); + state_plus_delta += parameter_blocks_[i]->Size(); + } + return true; +} + +void Program::SetParameterOffsetsAndIndex() { + // Set positions for all parameters appearing as arguments to residuals to one + // past the end of the parameter block array. + for (int i = 0; i < residual_blocks_.size(); ++i) { + ResidualBlock* residual_block = residual_blocks_[i]; + for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) { + residual_block->parameter_blocks()[j]->set_index(-1); + } + } + // For parameters that appear in the program, set their position and offset. + int state_offset = 0; + int delta_offset = 0; + for (int i = 0; i < parameter_blocks_.size(); ++i) { + parameter_blocks_[i]->set_index(i); + parameter_blocks_[i]->set_state_offset(state_offset); + parameter_blocks_[i]->set_delta_offset(delta_offset); + state_offset += parameter_blocks_[i]->Size(); + delta_offset += parameter_blocks_[i]->LocalSize(); + } +} + +int Program::NumResidualBlocks() const { + return residual_blocks_.size(); +} + +int Program::NumParameterBlocks() const { + return parameter_blocks_.size(); +} + +int Program::NumResiduals() const { + int num_residuals = 0; + for (int i = 0; i < residual_blocks_.size(); ++i) { + num_residuals += residual_blocks_[i]->NumResiduals(); + } + return num_residuals; +} + +int Program::NumParameters() const { + int num_parameters = 0; + for (int i = 0; i < parameter_blocks_.size(); ++i) { + num_parameters += parameter_blocks_[i]->Size(); + } + return num_parameters; +} + +int Program::NumEffectiveParameters() const { + int num_parameters = 0; + for (int i = 0; i < parameter_blocks_.size(); ++i) { + num_parameters += parameter_blocks_[i]->LocalSize(); + } + return num_parameters; +} + +int Program::MaxScratchDoublesNeededForEvaluate() const { + // Compute the scratch space needed for evaluate. + int max_scratch_bytes_for_evaluate = 0; + for (int i = 0; i < residual_blocks_.size(); ++i) { + max_scratch_bytes_for_evaluate = + max(max_scratch_bytes_for_evaluate, + residual_blocks_[i]->NumScratchDoublesForEvaluate()); + } + return max_scratch_bytes_for_evaluate; +} + +int Program::MaxDerivativesPerResidualBlock() const { + int max_derivatives = 0; + for (int i = 0; i < residual_blocks_.size(); ++i) { + int derivatives = 0; + ResidualBlock* residual_block = residual_blocks_[i]; + int num_parameters = residual_block->NumParameterBlocks(); + for (int j = 0; j < num_parameters; ++j) { + derivatives += residual_block->NumResiduals() * + residual_block->parameter_blocks()[j]->LocalSize(); + } + max_derivatives = max(max_derivatives, derivatives); + } + return max_derivatives; +} + +int Program::MaxParametersPerResidualBlock() const { + int max_parameters = 0; + for (int i = 0; i < residual_blocks_.size(); ++i) { + max_parameters = max(max_parameters, + residual_blocks_[i]->NumParameterBlocks()); + } + return max_parameters; +} + +bool Program::Evaluate(double* cost, double* residuals) { + *cost = 0.0; + + // Scratch space is only needed if residuals is NULL. + scoped_array scratch; + if (residuals == NULL) { + scratch.reset(new double[MaxScratchDoublesNeededForEvaluate()]); + } else { + // TODO(keir): Is this needed? Check by removing the equivalent statement in + // dense_evaluator.cc and running the tests. + VectorRef(residuals, NumResiduals()).setZero(); + } + + for (int i = 0; i < residual_blocks_.size(); ++i) { + ResidualBlock* residual_block = residual_blocks_[i]; + + // Evaluate the cost function for this residual. + double residual_cost; + if (!residual_block->Evaluate(&residual_cost, + residuals, + NULL, // No jacobian. + scratch.get())) { + return false; + } + + // Accumulate residual cost into the total cost. + *cost += residual_cost; + + // Update the residuals cursor. + if (residuals != NULL) { + residuals += residual_block->NumResiduals(); + } + } + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.h b/extern/libmv/third_party/ceres/internal/ceres/program.h new file mode 100644 index 00000000000..113d352d562 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/program.h @@ -0,0 +1,128 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_PROGRAM_H_ +#define CERES_INTERNAL_PROGRAM_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +class ParameterBlock; +class ProblemImpl; +class ResidualBlock; + +// A nonlinear least squares optimization problem. This is different from the +// similarly-named "Problem" object, which offers a mutation interface for +// adding and modifying parameters and residuals. The Program contains the core +// part of the Problem, which is the parameters and the residuals, stored in a +// particular ordering. The ordering is critical, since it defines the mapping +// between (residual, parameter) pairs and a position in the jacobian of the +// objective function. Various parts of Ceres transform one Program into +// another; for example, the first stage of solving involves stripping all +// constant parameters and residuals. This is in contrast with Problem, which is +// not built for transformation. +class Program { + public: + Program(); + explicit Program(const Program& program); + + // The ordered parameter and residual blocks for the program. + const vector& parameter_blocks() const; + const vector& residual_blocks() const; + vector* mutable_parameter_blocks(); + vector* mutable_residual_blocks(); + + // Serialize to/from the program and update states. + // + // NOTE: Setting the state of a parameter block can trigger the + // computation of the Jacobian of its local parameterization. If + // this computation fails for some reason, then this method returns + // false and the state of the parameter blocks cannot be trusted. + bool StateVectorToParameterBlocks(const double *state); + void ParameterBlocksToStateVector(double *state) const; + + // Copy internal state out to the user's parameters. + void CopyParameterBlockStateToUserState(); + + // Update a state vector for the program given a delta. + bool Plus(const double* state, + const double* delta, + double* state_plus_delta) const; + + // Set the parameter indices and offsets. This permits mapping backward + // from a ParameterBlock* to an index in the parameter_blocks() vector. For + // any parameter block p, after calling SetParameterOffsetsAndIndex(), it + // is true that + // + // parameter_blocks()[p->index()] == p + // + // If a parameter appears in a residual but not in the parameter block, then + // it will have an index of -1. + // + // This also updates p->state_offset() and p->delta_offset(), which are the + // position of the parameter in the state and delta vector respectively. + void SetParameterOffsetsAndIndex(); + + // See problem.h for what these do. + int NumParameterBlocks() const; + int NumParameters() const; + int NumEffectiveParameters() const; + int NumResidualBlocks() const; + int NumResiduals() const; + + int MaxScratchDoublesNeededForEvaluate() const; + int MaxDerivativesPerResidualBlock() const; + int MaxParametersPerResidualBlock() const; + + // Evaluate the cost and maybe the residuals for the program. If residuals is + // NULL, then residuals are not calculated. If the jacobian is needed, instead + // use the various evaluators (e.g. dense_evaluator.h). + // + // This is a trivial implementation of evaluate not intended for use in the + // core solving loop. The other evaluators, which support constructing the + // jacobian in addition to the cost and residuals, are considerably + // complicated by the need to construct the jacobian. + bool Evaluate(double* cost, double* residuals); + + private: + // The Program does not own the ParameterBlock or ResidualBlock objects. + vector parameter_blocks_; + vector residual_blocks_; + + friend class ProblemImpl; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PROGRAM_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h new file mode 100644 index 00000000000..7ec74b1b269 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h @@ -0,0 +1,279 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// The ProgramEvaluator runs the cost functions contained in each residual block +// and stores the result into a jacobian. The particular type of jacobian is +// abstracted out using two template parameters: +// +// - An "EvaluatePreparer" that is responsible for creating the array with +// pointers to the jacobian blocks where the cost function evaluates to. +// - A "JacobianWriter" that is responsible for storing the resulting +// jacobian blocks in the passed sparse matrix. +// +// This abstraction affords an efficient evaluator implementation while still +// supporting writing to multiple sparse matrix formats. For example, when the +// ProgramEvaluator is parameterized for writing to block sparse matrices, the +// residual jacobians are written directly into their final position in the +// block sparse matrix by the user's CostFunction; there is no copying. +// +// The evaluation is threaded with OpenMP. +// +// The EvaluatePreparer and JacobianWriter interfaces are as follows: +// +// class EvaluatePreparer { +// // Prepare the jacobians array for use as the destination of a call to +// // a cost function's evaluate method. +// void Prepare(const ResidualBlock* residual_block, +// int residual_block_index, +// SparseMatrix* jacobian, +// double** jacobians); +// } +// +// class JacobianWriter { +// // Create a jacobian that this writer can write. Same as +// // Evaluator::CreateJacobian. +// SparseMatrix* CreateJacobian() const; +// +// // Create num_threads evaluate preparers. Caller owns result which must +// // be freed with delete[]. Resulting preparers are valid while *this is. +// EvaluatePreparer* CreateEvaluatePreparers(int num_threads); +// +// // Write the block jacobians from a residual block evaluation to the +// // larger sparse jacobian. +// void Write(int residual_id, +// int residual_offset, +// double** jacobians, +// SparseMatrix* jacobian); +// } +// +// Note: The ProgramEvaluator is not thread safe, since internally it maintains +// some per-thread scratch space. + +#ifndef CERES_INTERNAL_PROGRAM_EVALUATOR_H_ +#define CERES_INTERNAL_PROGRAM_EVALUATOR_H_ + +#ifdef CERES_USE_OPENMP +#include +#endif + +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +template +class ProgramEvaluator : public Evaluator { + public: + ProgramEvaluator(const Evaluator::Options &options, Program* program) + : options_(options), + program_(program), + jacobian_writer_(options, program), + evaluate_preparers_( + jacobian_writer_.CreateEvaluatePreparers(options.num_threads)) { +#ifndef CERES_USE_OPENMP + CHECK_EQ(1, options_.num_threads) + << "OpenMP support is not compiled into this binary; " + << "only options.num_threads=1 is supported."; +#endif + + BuildResidualLayout(*program, &residual_layout_); + evaluate_scratch_.reset(CreateEvaluatorScratch(*program, + options.num_threads)); + } + + // Implementation of Evaluator interface. + SparseMatrix* CreateJacobian() const { + return jacobian_writer_.CreateJacobian(); + } + + bool Evaluate(const double* state, + double* cost, + double* residuals, + SparseMatrix* jacobian) { + // The parameters are stateful, so set the state before evaluating. + if (!program_->StateVectorToParameterBlocks(state)) { + return false; + } + + if (jacobian) { + jacobian->SetZero(); + } + + // Each thread gets it's own cost and evaluate scratch space. + for (int i = 0; i < options_.num_threads; ++i) { + evaluate_scratch_[i].cost = 0.0; + } + + // This bool is used to disable the loop if an error is encountered + // without breaking out of it. The remaining loop iterations are still run, + // but with an empty body, and so will finish quickly. + bool abort = false; + int num_residual_blocks = program_->NumResidualBlocks(); +#pragma omp parallel for num_threads(options_.num_threads) + for (int i = 0; i < num_residual_blocks; ++i) { +// Disable the loop instead of breaking, as required by OpenMP. +#pragma omp flush(abort) + if (abort) { + continue; + } + +#ifdef CERES_USE_OPENMP + int thread_id = omp_get_thread_num(); +#else + int thread_id = 0; +#endif + EvaluatePreparer* preparer = &evaluate_preparers_[thread_id]; + EvaluateScratch* scratch = &evaluate_scratch_[thread_id]; + + // Prepare block residuals if requested. + const ResidualBlock* residual_block = program_->residual_blocks()[i]; + double* block_residuals = (residuals != NULL) + ? (residuals + residual_layout_[i]) + : NULL; + + // Prepare block jacobians if requested. + double** block_jacobians = NULL; + if (jacobian != NULL) { + preparer->Prepare(residual_block, + i, + jacobian, + scratch->jacobian_block_ptrs.get()); + block_jacobians = scratch->jacobian_block_ptrs.get(); + } + + // Evaluate the cost, residuals, and jacobians. + double block_cost; + if (!residual_block->Evaluate(&block_cost, + block_residuals, + block_jacobians, + scratch->scratch.get())) { + abort = true; +// This ensures that the OpenMP threads have a consistent view of 'abort'. Do +// the flush inside the failure case so that there is usually only one +// synchronization point per loop iteration instead of two. +#pragma omp flush(abort) + continue; + } + + scratch->cost += block_cost; + + if (jacobian != NULL) { + jacobian_writer_.Write(i, + residual_layout_[i], + block_jacobians, + jacobian); + } + } + + if (!abort) { + // Sum the cost from each thread. + (*cost) = 0.0; + for (int i = 0; i < options_.num_threads; ++i) { + (*cost) += evaluate_scratch_[i].cost; + } + } + return !abort; + } + + bool Plus(const double* state, + const double* delta, + double* state_plus_delta) const { + return program_->Plus(state, delta, state_plus_delta); + } + + int NumParameters() const { + return program_->NumParameters(); + } + int NumEffectiveParameters() const { + return program_->NumEffectiveParameters(); + } + + int NumResiduals() const { + return program_->NumResiduals(); + } + + private: + struct EvaluateScratch { + void Init(int max_parameters_per_residual_block, + int max_scratch_doubles_needed_for_evaluate) { + jacobian_block_ptrs.reset( + new double*[max_parameters_per_residual_block]); + scratch.reset(new double[max_scratch_doubles_needed_for_evaluate]); + } + + double cost; + scoped_array scratch; + scoped_array jacobian_block_ptrs; + }; + + static void BuildResidualLayout(const Program& program, + vector* residual_layout) { + const vector& residual_blocks = program.residual_blocks(); + residual_layout->resize(program.NumResidualBlocks()); + int residual_pos = 0; + for (int i = 0; i < residual_blocks.size(); ++i) { + const int num_residuals = residual_blocks[i]->NumResiduals(); + (*residual_layout)[i] = residual_pos; + residual_pos += num_residuals; + } + } + + // Create scratch space for each thread evaluating the program. + static EvaluateScratch* CreateEvaluatorScratch(const Program& program, + int num_threads) { + int max_parameters_per_residual_block = + program.MaxParametersPerResidualBlock(); + int max_scratch_doubles_needed_for_evaluate = + program.MaxScratchDoublesNeededForEvaluate(); + + EvaluateScratch* evaluate_scratch = new EvaluateScratch[num_threads]; + for (int i = 0; i < num_threads; i++) { + evaluate_scratch[i].Init(max_parameters_per_residual_block, + max_scratch_doubles_needed_for_evaluate); + } + return evaluate_scratch; + } + + Evaluator::Options options_; + Program* program_; + JacobianWriter jacobian_writer_; + scoped_array evaluate_preparers_; + scoped_array evaluate_scratch_; + vector residual_layout_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PROGRAM_EVALUATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/random.h b/extern/libmv/third_party/ceres/internal/ceres/random.h new file mode 100644 index 00000000000..769e0b4dd27 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/random.h @@ -0,0 +1,47 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_RANDOM_H_ +#define CERES_INTERNAL_RANDOM_H_ + +namespace ceres { + +inline double RandDouble() { + double r = rand(); + return r / RAND_MAX; +} + +inline int Uniform(int n) { + return rand() % n; +} + +} // namespace ceres + +#endif // CERES_INTERNAL_RANDOM_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc new file mode 100644 index 00000000000..03867891dba --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc @@ -0,0 +1,212 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/residual_block.h" + +#include +#include +#include + +#include "ceres/corrector.h" +#include "ceres/parameter_block.h" +#include "ceres/residual_block_utils.h" +#include "ceres/cost_function.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/fixed_array.h" +#include "ceres/local_parameterization.h" +#include "ceres/loss_function.h" + +namespace ceres { +namespace internal { + +ResidualBlock::ResidualBlock(const CostFunction* cost_function, + const LossFunction* loss_function, + const vector& parameter_blocks) + : cost_function_(cost_function), + loss_function_(loss_function), + parameter_blocks_( + new ParameterBlock* [ + cost_function->parameter_block_sizes().size()]) { + std::copy(parameter_blocks.begin(), + parameter_blocks.end(), + parameter_blocks_.get()); +} + +bool ResidualBlock::Evaluate(double* cost, + double* residuals, + double** jacobians, + double* scratch) const { + const int num_parameter_blocks = NumParameterBlocks(); + const int num_residuals = cost_function_->num_residuals(); + + // Collect the parameters from their blocks. This will rarely allocate, since + // residuals taking more than 8 parameter block arguments are rare. + FixedArray parameters(num_parameter_blocks); + for (int i = 0; i < num_parameter_blocks; ++i) { + parameters[i] = parameter_blocks_[i]->state(); + } + + // Put pointers into the scratch space into global_jacobians as appropriate. + FixedArray global_jacobians(num_parameter_blocks); + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + if (jacobians[i] != NULL && + parameter_block->LocalParameterizationJacobian() != NULL) { + global_jacobians[i] = scratch; + scratch += num_residuals * parameter_block->Size(); + } else { + global_jacobians[i] = jacobians[i]; + } + } + } + + // If the caller didn't request residuals, use the scratch space for them. + bool outputting_residuals = (residuals != NULL); + if (!outputting_residuals) { + residuals = scratch; + } + + // Invalidate the evaluation buffers so that we can check them after + // the CostFunction::Evaluate call, to see if all the return values + // that were required were written to and that they are finite. + double** eval_jacobians = (jacobians != NULL) ? global_jacobians.get() : NULL; + + InvalidateEvaluation(*this, cost, residuals, eval_jacobians); + + if (!cost_function_->Evaluate(parameters.get(), residuals, eval_jacobians) || + !IsEvaluationValid(*this, + parameters.get(), + cost, + residuals, + eval_jacobians)) { + string message = + "\n\n" + "Error in evaluating the ResidualBlock.\n\n" + "There are two possible reasons. Either the CostFunction did not evaluate and fill all \n" // NOLINT + "residual and jacobians that were requested or there was a non-finite value (nan/infinite)\n" // NOLINT + "generated during the or jacobian computation. \n\n" + + EvaluationToString(*this, + parameters.get(), + cost, + residuals, + eval_jacobians); + LOG(WARNING) << message; + return false; + } + + double squared_norm = VectorRef(residuals, num_residuals).squaredNorm(); + + // Update the jacobians with the local parameterizations. + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + if (jacobians[i] != NULL) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + + // Apply local reparameterization to the jacobians. + if (parameter_block->LocalParameterizationJacobian() != NULL) { + ConstMatrixRef local_to_global( + parameter_block->LocalParameterizationJacobian(), + parameter_block->Size(), + parameter_block->LocalSize()); + MatrixRef global_jacobian(global_jacobians[i], + num_residuals, + parameter_block->Size()); + MatrixRef local_jacobian(jacobians[i], + num_residuals, + parameter_block->LocalSize()); + local_jacobian.noalias() = global_jacobian * local_to_global; + } + } + } + } + + if (loss_function_ == NULL) { + *cost = 0.5 * squared_norm; + return true; + } + + double rho[3]; + loss_function_->Evaluate(squared_norm, rho); + *cost = 0.5 * rho[0]; + + // No jacobians and not outputting residuals? All done. Doing an early exit + // here avoids constructing the "Corrector" object below in a common case. + if (jacobians == NULL && !outputting_residuals) { + return true; + } + + // Correct for the effects of the loss function. The jacobians need to be + // corrected before the residuals, since they use the uncorrected residuals. + Corrector correct(squared_norm, rho); + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + if (jacobians[i] != NULL) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + + // Correct the jacobians for the loss function. + correct.CorrectJacobian(num_residuals, + parameter_block->LocalSize(), + residuals, + jacobians[i]); + } + } + } + + // Correct the residuals with the loss function. + if (outputting_residuals) { + correct.CorrectResiduals(num_residuals, residuals); + } + return true; +} + +int ResidualBlock::NumScratchDoublesForEvaluate() const { + // Compute the amount of scratch space needed to store the full-sized + // jacobians. For parameters that have no local parameterization no storage + // is needed and the passed-in jacobian array is used directly. Also include + // space to store the residuals, which is needed for cost-only evaluations. + // This is slightly pessimistic, since both won't be needed all the time, but + // the amount of excess should not cause problems for the caller. + int num_parameters = NumParameterBlocks(); + int scratch_doubles = 1; + for (int i = 0; i < num_parameters; ++i) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + if (!parameter_block->IsConstant() && + parameter_block->LocalParameterizationJacobian() != NULL) { + scratch_doubles += parameter_block->Size(); + } + } + scratch_doubles *= NumResiduals(); + return scratch_doubles; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block.h b/extern/libmv/third_party/ceres/internal/ceres/residual_block.h new file mode 100644 index 00000000000..e0a06e78958 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block.h @@ -0,0 +1,124 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) +// +// Purpose : Class and struct definitions for parameter and residual blocks. + +#ifndef CERES_INTERNAL_RESIDUAL_BLOCK_H_ +#define CERES_INTERNAL_RESIDUAL_BLOCK_H_ + +#include + +#include "ceres/cost_function.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +class LossFunction; + +namespace internal { + +class ParameterBlock; + +// A term in the least squares problem. The mathematical form of each term in +// the overall least-squares cost function is: +// +// 1 +// --- loss_function( || cost_function(block1, block2, ...) ||^2 ), +// 2 +// +// Storing the cost function and the loss function separately permits optimizing +// the problem with standard non-linear least techniques, without requiring a +// more general non-linear solver. +// +// The residual block stores pointers to but does not own the cost functions, +// loss functions, and parameter blocks. +class ResidualBlock { + public: + ResidualBlock(const CostFunction* cost_function, + const LossFunction* loss_function, + const vector& parameter_blocks); + + // Evaluates the residual term, storing the scalar cost in *cost, the residual + // components in *residuals, and the jacobians between the parameters and + // residuals in jacobians[i], in row-major order. If residuals is NULL, the + // residuals are not computed. If jacobians is NULL, no jacobians are + // computed. If jacobians[i] is NULL, then the jacobian for that parameter is + // not computed. + // + // Evaluate needs scratch space which must be supplied by the caller via + // scratch. The array should have at least NumScratchDoublesForEvaluate() + // space available. + // + // The return value indicates the success or failure. If the function returns + // false, the caller should expect the the output memory locations to have + // been modified. + // + // The returned cost and jacobians have had robustification and local + // parameterizations applied already; for example, the jacobian for a + // 4-dimensional quaternion parameter using the "QuaternionParameterization" + // is num_residuals by 3 instead of num_residuals by 4. + bool Evaluate(double* cost, + double* residuals, + double** jacobians, + double* scratch) const; + + const CostFunction* cost_function() const { return cost_function_; } + const LossFunction* loss_function() const { return loss_function_; } + + // Access the parameter blocks for this residual. The array has size + // NumParameterBlocks(). + ParameterBlock* const* parameter_blocks() const { + return parameter_blocks_.get(); + } + + // Number of variable blocks that this residual term depends on. + int NumParameterBlocks() const { + return cost_function_->parameter_block_sizes().size(); + } + + // The size of the residual vector returned by this residual function. + int NumResiduals() const { return cost_function_->num_residuals(); } + + // The minimum amount of scratch space needed to pass to Evaluate(). + int NumScratchDoublesForEvaluate() const; + + private: + const CostFunction* cost_function_; + const LossFunction* loss_function_; + scoped_array parameter_blocks_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_RESIDUAL_BLOCK_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc new file mode 100644 index 00000000000..28e03130844 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc @@ -0,0 +1,185 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/residual_block_utils.h" + +#include +#include +#include +#include +#include "ceres/residual_block.h" +#include "ceres/parameter_block.h" +#include "ceres/stringprintf.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" + +#ifdef _MSC_VER +# define isfinite _finite +#endif + +namespace ceres { +namespace internal { + +// It is a near impossibility that user code generates this exact +// value in normal operation, thus we will use it to fill arrays +// before passing them to user code. If on return an element of the +// array still contains this value, we will assume that the user code +// did not write to that memory location. +static const double kImpossibleValue = 1e302; + +bool IsArrayValid(const int size, const double* x) { + if (x != NULL) { + for (int i = 0; i < size; ++i) { + if (!isfinite(x[i]) || (x[i] == kImpossibleValue)) { + return false; + } + } + } + return true; +} + +void InvalidateArray(const int size, double* x) { + if (x != NULL) { + for (int i = 0; i < size; ++i) { + x[i] = kImpossibleValue; + } + } +} + +void InvalidateEvaluation(const ResidualBlock& block, + double* cost, + double* residuals, + double** jacobians) { + const int num_parameter_blocks = block.NumParameterBlocks(); + const int num_residuals = block.NumResiduals(); + + InvalidateArray(1, cost); + InvalidateArray(num_residuals, residuals); + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + const int parameter_block_size = block.parameter_blocks()[i]->Size(); + InvalidateArray(num_residuals * parameter_block_size, jacobians[i]); + } + } +} + +// Utility routine to print an array of doubles to a string. If the +// array pointer is NULL, it is treated as an array of zeros. +void AppendArrayToString(const int size, const double* x, string* result) { + for (int i = 0; i < size; ++i) { + if (x == NULL) { + StringAppendF(result, "Not Computed "); + } else { + if (x[i] == kImpossibleValue) { + StringAppendF(result, "Uninitialized "); + } else { + StringAppendF(result, "%12g ", x[i]); + } + } + } +} + +string EvaluationToString(const ResidualBlock& block, + double const* const* parameters, + double* cost, + double* residuals, + double** jacobians) { + CHECK_NOTNULL(cost); + CHECK_NOTNULL(residuals); + + const int num_parameter_blocks = block.NumParameterBlocks(); + const int num_residuals = block.NumResiduals(); + string result = ""; + + StringAppendF(&result, + "Residual Block size: %d parameter blocks x %d residuals\n\n", + num_parameter_blocks, num_residuals); + result += + "For each parameter block, the value of the parameters are printed in the first column \n" // NOLINT + "and the value of the jacobian under the corresponding residual. If a ParameterBlock was \n" // NOLINT + "held constant then the corresponding jacobian is printed as 'Not Computed'. If an entry \n" // NOLINT + "of the Jacobian/residual array was requested but was not written to by user code, it is \n" // NOLINT + "indicated by 'Uninitialized'. This is an error. Residuals or Jacobian values evaluating \n" // NOLINT + "to Inf or NaN is also an error. \n\n"; // NOLINT + + string space = "Residuals: "; + result += space; + AppendArrayToString(num_residuals, residuals, &result); + StringAppendF(&result, "\n\n"); + + for (int i = 0; i < num_parameter_blocks; ++i) { + const int parameter_block_size = block.parameter_blocks()[i]->Size(); + StringAppendF( + &result, "Parameter Block %d, size: %d\n", i, parameter_block_size); + StringAppendF(&result, "\n"); + for (int j = 0; j < parameter_block_size; ++j) { + AppendArrayToString(1, parameters[i] + j, &result); + StringAppendF(&result, "| "); + for (int k = 0; k < num_residuals; ++k) { + AppendArrayToString(1, + (jacobians != NULL && jacobians[i] != NULL) + ? jacobians[i] + k * parameter_block_size + j + : NULL, + &result); + } + StringAppendF(&result, "\n"); + } + StringAppendF(&result, "\n"); + } + StringAppendF(&result, "\n"); + return result; +} + +bool IsEvaluationValid(const ResidualBlock& block, + double const* const* parameters, + double* cost, + double* residuals, + double** jacobians) { + const int num_parameter_blocks = block.NumParameterBlocks(); + const int num_residuals = block.NumResiduals(); + + if (!IsArrayValid(num_residuals, residuals)) { + return false; + } + + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + const int parameter_block_size = block.parameter_blocks()[i]->Size(); + if (!IsArrayValid(num_residuals * parameter_block_size, jacobians[i])) { + return false; + } + } + } + + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h new file mode 100644 index 00000000000..228867cc60c --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h @@ -0,0 +1,89 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Utility routines for ResidualBlock evaluation. +// +// These are useful for detecting two common class of errors. +// +// 1. Uninitialized memory - where the user for some reason did not +// compute part of a cost/residual/jacobian. +// +// 2. Numerical failure while computing the cost/residual/jacobian, +// e.g. NaN, infinities etc. This is particularly useful since the +// automatic differentiation code does computations that are not +// evident to the user and can silently generate hard to debug errors. + +#ifndef CERES_INTERNAL_RESIDUAL_BLOCK_UTILS_H_ +#define CERES_INTERNAL_RESIDUAL_BLOCK_UTILS_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +class ResidualBlock; + +// Fill the array x with an impossible value that the user code is +// never expected to compute. +void InvalidateArray(int size, double* x); + +// Check if all the entries of the array x are valid, i.e. all the +// values in the array should be finite and none of them should be +// equal to the "impossible" value used by InvalidateArray. +bool IsArrayValid(int size, const double* x); + +// Invalidate cost, resdual and jacobian arrays (if not NULL). +void InvalidateEvaluation(const ResidualBlock& block, + double* cost, + double* residuals, + double** jacobians); + +// Check if any of the arrays cost, residuals or jacobians contains an +// NaN, return true if it does. +bool IsEvaluationValid(const ResidualBlock& block, + double const* const* parameters, + double* cost, + double* residuals, + double** jacobians); + +// Create a string representation of the Residual block containing the +// value of the parameters, residuals and jacobians if present. +// Useful for debugging output. +string EvaluationToString(const ResidualBlock& block, + double const* const* parameters, + double* cost, + double* residuals, + double** jacobians); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_RESIDUAL_BLOCK_UTILS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc new file mode 100644 index 00000000000..ac6d8aa279a --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc @@ -0,0 +1,218 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Based on the templated version in public/numeric_diff_cost_function.h. + +#include "ceres/runtime_numeric_diff_cost_function.h" + +#include +#include +#include + +#include +#include "Eigen/Dense" +#include "ceres/cost_function.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { +namespace { + +bool EvaluateJacobianForParameterBlock(const CostFunction* function, + int parameter_block_size, + int parameter_block, + RuntimeNumericDiffMethod method, + double relative_step_size, + double const* residuals_at_eval_point, + double** parameters, + double** jacobians) { + using Eigen::Map; + using Eigen::Matrix; + using Eigen::Dynamic; + using Eigen::RowMajor; + + typedef Matrix ResidualVector; + typedef Matrix ParameterVector; + typedef Matrix JacobianMatrix; + + int num_residuals = function->num_residuals(); + + Map parameter_jacobian(jacobians[parameter_block], + num_residuals, + parameter_block_size); + + // Mutate one element at a time and then restore. + Map x_plus_delta(parameters[parameter_block], + parameter_block_size); + ParameterVector x(x_plus_delta); + ParameterVector step_size = x.array().abs() * relative_step_size; + + // To handle cases where a paremeter is exactly zero, instead use the mean + // step_size for the other dimensions. + double fallback_step_size = step_size.sum() / step_size.rows(); + if (fallback_step_size == 0.0) { + // If all the parameters are zero, there's no good answer. Use the given + // relative step_size as absolute step_size and hope for the best. + fallback_step_size = relative_step_size; + } + + // For each parameter in the parameter block, use finite differences to + // compute the derivative for that parameter. + for (int j = 0; j < parameter_block_size; ++j) { + if (step_size(j) == 0.0) { + // The parameter is exactly zero, so compromise and use the mean step_size + // from the other parameters. This can break in many cases, but it's hard + // to pick a good number without problem specific knowledge. + step_size(j) = fallback_step_size; + } + x_plus_delta(j) = x(j) + step_size(j); + + ResidualVector residuals(num_residuals); + if (!function->Evaluate(parameters, &residuals[0], NULL)) { + // Something went wrong; bail. + return false; + } + + // Compute this column of the jacobian in 3 steps: + // 1. Store residuals for the forward part. + // 2. Subtract residuals for the backward (or 0) part. + // 3. Divide out the run. + parameter_jacobian.col(j) = residuals; + + double one_over_h = 1 / step_size(j); + if (method == CENTRAL) { + // Compute the function on the other side of x(j). + x_plus_delta(j) = x(j) - step_size(j); + + if (!function->Evaluate(parameters, &residuals[0], NULL)) { + // Something went wrong; bail. + return false; + } + parameter_jacobian.col(j) -= residuals; + one_over_h /= 2; + } else { + // Forward difference only; reuse existing residuals evaluation. + parameter_jacobian.col(j) -= + Map(residuals_at_eval_point, num_residuals); + } + x_plus_delta(j) = x(j); // Restore x_plus_delta. + + // Divide out the run to get slope. + parameter_jacobian.col(j) *= one_over_h; + } + return true; +} + +class RuntimeNumericDiffCostFunction : public CostFunction { + public: + RuntimeNumericDiffCostFunction(const CostFunction* function, + RuntimeNumericDiffMethod method, + double relative_step_size) + : function_(function), + method_(method), + relative_step_size_(relative_step_size) { + *mutable_parameter_block_sizes() = function->parameter_block_sizes(); + set_num_residuals(function->num_residuals()); + } + + virtual ~RuntimeNumericDiffCostFunction() { } + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + // Get the function value (residuals) at the the point to evaluate. + bool success = function_->Evaluate(parameters, residuals, NULL); + if (!success) { + // Something went wrong; ignore the jacobian. + return false; + } + if (!jacobians) { + // Nothing to do; just forward. + return true; + } + + const vector& block_sizes = function_->parameter_block_sizes(); + CHECK(!block_sizes.empty()); + + // Create local space for a copy of the parameters which will get mutated. + int parameters_size = accumulate(block_sizes.begin(), block_sizes.end(), 0); + vector parameters_copy(parameters_size); + vector parameters_references_copy(block_sizes.size()); + parameters_references_copy[0] = ¶meters_copy[0]; + for (int block = 1; block < block_sizes.size(); ++block) { + parameters_references_copy[block] = parameters_references_copy[block - 1] + + block_sizes[block - 1]; + } + + // Copy the parameters into the local temp space. + for (int block = 0; block < block_sizes.size(); ++block) { + memcpy(parameters_references_copy[block], + parameters[block], + block_sizes[block] * sizeof(*parameters[block])); + } + + for (int block = 0; block < block_sizes.size(); ++block) { + if (!jacobians[block]) { + // No jacobian requested for this parameter / residual pair. + continue; + } + if (!EvaluateJacobianForParameterBlock(function_, + block_sizes[block], + block, + method_, + relative_step_size_, + residuals, + ¶meters_references_copy[0], + jacobians)) { + return false; + } + } + return true; + } + + private: + const CostFunction* function_; + RuntimeNumericDiffMethod method_; + double relative_step_size_; +}; + +} // namespace + +CostFunction* CreateRuntimeNumericDiffCostFunction( + const CostFunction* cost_function, + RuntimeNumericDiffMethod method, + double relative_step_size) { + return new RuntimeNumericDiffCostFunction(cost_function, + method, + relative_step_size); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h new file mode 100644 index 00000000000..01b57f92ef3 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h @@ -0,0 +1,87 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Create CostFunctions as needed by the least squares framework with jacobians +// computed via numeric differentiation. +// +// To get a numerically differentiated cost function, define a subclass of +// CostFunction such that the Evaluate() function ignores the jacobian +// parameter. The numeric differentiation wrapper will fill in the jacobian +// parameter if nececssary by repeatedly calling the Evaluate() function with +// small changes to the appropriate parameters, and computing the slope. This +// implementation is not templated (hence the "Runtime" prefix), which is a bit +// slower than but is more convenient than the templated version in +// numeric_diff_cost_function.h +// +// The numerically differentiated version of a cost function for a cost function +// can be constructed as follows: +// +// CostFunction* cost_function = +// CreateRuntimeNumericDiffCostFunction(new MyCostFunction(...), +// CENTRAL, +// TAKE_OWNERSHIP); +// +// The central difference method is considerably more accurate; consider using +// to start and only after that works, trying forward difference. +// +// TODO(keir): Characterize accuracy; mention pitfalls; provide alternatives. + +#ifndef CERES_INTERNAL_RUNTIME_NUMERIC_DIFF_COST_FUNCTION_H_ +#define CERES_INTERNAL_RUNTIME_NUMERIC_DIFF_COST_FUNCTION_H_ + +#include "ceres/cost_function.h" + +namespace ceres { +namespace internal { + +enum RuntimeNumericDiffMethod { + CENTRAL, + FORWARD, +}; + +// Create a cost function that evaluates the derivative with finite differences. +// The base cost_function's implementation of Evaluate() only needs to fill in +// the "residuals" argument and not the "jacobians". Any data written to the +// jacobians by the base cost_function is overwritten. +// +// Forward difference or central difference is selected with CENTRAL or FORWARD. +// The relative eps, which determines the step size for forward and central +// differencing, is set with relative eps. Caller owns the resulting cost +// function, and the resulting cost function does not own the base cost +// function. +CostFunction *CreateRuntimeNumericDiffCostFunction( + const CostFunction *cost_function, + RuntimeNumericDiffMethod method, + double relative_eps); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_RUNTIME_NUMERIC_DIFF_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc new file mode 100644 index 00000000000..2bc8cdd6bec --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc @@ -0,0 +1,285 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include +#include +#include +#include +#include "Eigen/Dense" +#include "ceres/block_random_access_dense_matrix.h" +#include "ceres/block_random_access_matrix.h" +#include "ceres/block_random_access_sparse_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/detect_structure.h" +#include "ceres/linear_solver.h" +#include "ceres/schur_complement_solver.h" +#include "ceres/suitesparse.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +LinearSolver::Summary SchurComplementSolver::SolveImpl( + BlockSparseMatrixBase* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + const time_t start_time = time(NULL); + if (!options_.constant_sparsity || (eliminator_.get() == NULL)) { + InitStorage(A->block_structure()); + DetectStructure(*A->block_structure(), + options_.num_eliminate_blocks, + &options_.row_block_size, + &options_.e_block_size, + &options_.f_block_size); + eliminator_.reset(CHECK_NOTNULL(SchurEliminatorBase::Create(options_))); + eliminator_->Init(options_.num_eliminate_blocks, A->block_structure()); + }; + const time_t init_time = time(NULL); + fill(x, x + A->num_cols(), 0.0); + + LinearSolver::Summary summary; + summary.num_iterations = 1; + summary.termination_type = FAILURE; + eliminator_->Eliminate(A, b, per_solve_options.D, lhs_.get(), rhs_.get()); + const time_t eliminate_time = time(NULL); + + double* reduced_solution = x + A->num_cols() - lhs_->num_cols(); + const bool status = SolveReducedLinearSystem(reduced_solution); + const time_t solve_time = time(NULL); + + if (!status) { + return summary; + } + + eliminator_->BackSubstitute(A, b, per_solve_options.D, reduced_solution, x); + const time_t backsubstitute_time = time(NULL); + summary.termination_type = TOLERANCE; + + VLOG(2) << "time (sec) total: " << backsubstitute_time - start_time + << " init: " << init_time - start_time + << " eliminate: " << eliminate_time - init_time + << " solve: " << solve_time - eliminate_time + << " backsubstitute: " << backsubstitute_time - solve_time; + return summary; +} + +// Initialize a BlockRandomAccessDenseMatrix to store the Schur +// complement. +void DenseSchurComplementSolver::InitStorage( + const CompressedRowBlockStructure* bs) { + const int num_eliminate_blocks = options().num_eliminate_blocks; + const int num_col_blocks = bs->cols.size(); + + vector blocks(num_col_blocks - num_eliminate_blocks, 0); + for (int i = num_eliminate_blocks, j = 0; + i < num_col_blocks; + ++i, ++j) { + blocks[j] = bs->cols[i].size; + } + + set_lhs(new BlockRandomAccessDenseMatrix(blocks)); + set_rhs(new double[lhs()->num_rows()]); +} + +// Solve the system Sx = r, assuming that the matrix S is stored in a +// BlockRandomAccessDenseMatrix. The linear system is solved using +// Eigen's Cholesky factorization. +bool DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { + const BlockRandomAccessDenseMatrix* m = + down_cast(lhs()); + const int num_rows = m->num_rows(); + + // The case where there are no f blocks, and the system is block + // diagonal. + if (num_rows == 0) { + return true; + } + + // TODO(sameeragarwal): Add proper error handling; this completely ignores + // the quality of the solution to the solve. + VectorRef(solution, num_rows) = + ConstMatrixRef(m->values(), num_rows, num_rows) + .selfadjointView() + .ldlt() + .solve(ConstVectorRef(rhs(), num_rows)); + + return true; +} + +#ifndef CERES_NO_SUITESPARSE +SparseSchurComplementSolver::SparseSchurComplementSolver( + const LinearSolver::Options& options) + : SchurComplementSolver(options), + symbolic_factor_(NULL) { +} + +SparseSchurComplementSolver::~SparseSchurComplementSolver() { + if (symbolic_factor_ != NULL) { + ss_.Free(symbolic_factor_); + symbolic_factor_ = NULL; + } +} + +// Determine the non-zero blocks in the Schur Complement matrix, and +// initialize a BlockRandomAccessSparseMatrix object. +void SparseSchurComplementSolver::InitStorage( + const CompressedRowBlockStructure* bs) { + const int num_eliminate_blocks = options().num_eliminate_blocks; + const int num_col_blocks = bs->cols.size(); + const int num_row_blocks = bs->rows.size(); + + vector blocks(num_col_blocks - num_eliminate_blocks, 0); + for (int i = num_eliminate_blocks; i < num_col_blocks; ++i) { + blocks[i - num_eliminate_blocks] = bs->cols[i].size; + } + + set > block_pairs; + for (int i = 0; i < blocks.size(); ++i) { + block_pairs.insert(make_pair(i, i)); + } + + int r = 0; + while (r < num_row_blocks) { + int e_block_id = bs->rows[r].cells.front().block_id; + if (e_block_id >= num_eliminate_blocks) { + break; + } + vector f_blocks; + + // Add to the chunk until the first block in the row is + // different than the one in the first row for the chunk. + for (; r < num_row_blocks; ++r) { + const CompressedRow& row = bs->rows[r]; + if (row.cells.front().block_id != e_block_id) { + break; + } + + // Iterate over the blocks in the row, ignoring the first + // block since it is the one to be eliminated. + for (int c = 1; c < row.cells.size(); ++c) { + const Cell& cell = row.cells[c]; + f_blocks.push_back(cell.block_id - num_eliminate_blocks); + } + } + + sort(f_blocks.begin(), f_blocks.end()); + f_blocks.erase(unique(f_blocks.begin(), f_blocks.end()), f_blocks.end()); + for (int i = 0; i < f_blocks.size(); ++i) { + for (int j = i + 1; j < f_blocks.size(); ++j) { + block_pairs.insert(make_pair(f_blocks[i], f_blocks[j])); + } + } + } + + // Remaing rows do not contribute to the chunks and directly go + // into the schur complement via an outer product. + for (; r < num_row_blocks; ++r) { + const CompressedRow& row = bs->rows[r]; + CHECK_GE(row.cells.front().block_id, num_eliminate_blocks); + for (int i = 0; i < row.cells.size(); ++i) { + int r_block1_id = row.cells[i].block_id - num_eliminate_blocks; + for (int j = 0; j < row.cells.size(); ++j) { + int r_block2_id = row.cells[j].block_id - num_eliminate_blocks; + if (r_block1_id <= r_block2_id) { + block_pairs.insert(make_pair(r_block1_id, r_block2_id)); + } + } + } + } + + set_lhs(new BlockRandomAccessSparseMatrix(blocks, block_pairs)); + set_rhs(new double[lhs()->num_rows()]); +} + +// Solve the system Sx = r, assuming that the matrix S is stored in a +// BlockRandomAccessSparseMatrix. The linear system is solved using +// CHOLMOD's sparse cholesky factorization routines. +bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { + // Extract the TripletSparseMatrix that is used for actually storing S. + TripletSparseMatrix* tsm = + const_cast( + down_cast(lhs())->matrix()); + + const int num_rows = tsm->num_rows(); + + // The case where there are no f blocks, and the system is block + // diagonal. + if (num_rows == 0) { + return true; + } + + cholmod_sparse* cholmod_lhs = ss_.CreateSparseMatrix(tsm); + // The matrix is symmetric, and the upper triangular part of the + // matrix contains the values. + cholmod_lhs->stype = 1; + + cholmod_dense* cholmod_rhs = + ss_.CreateDenseVector(const_cast(rhs()), num_rows, num_rows); + + // Symbolic factorization is computed if we don't already have one handy. + if (symbolic_factor_ == NULL) { + symbolic_factor_ = ss_.AnalyzeCholesky(cholmod_lhs); + } + + cholmod_dense* cholmod_solution = + ss_.SolveCholesky(cholmod_lhs, symbolic_factor_, cholmod_rhs); + + ss_.Free(cholmod_lhs); + cholmod_lhs = NULL; + ss_.Free(cholmod_rhs); + cholmod_rhs = NULL; + + // If sparsity is not constant across calls, then reset the symbolic + // factorization. + if (!options().constant_sparsity) { + ss_.Free(symbolic_factor_); + symbolic_factor_ = NULL; + } + + if (cholmod_solution == NULL) { + LOG(ERROR) << "CHOLMOD solve failed."; + return false; + } + + VectorRef(solution, num_rows) + = VectorRef(static_cast(cholmod_solution->x), num_rows); + ss_.Free(cholmod_solution); + return true; +} +#endif // CERES_NO_SUITESPARSE + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h new file mode 100644 index 00000000000..039bc09e3ce --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h @@ -0,0 +1,182 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_ +#define CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_ + +#include "ceres/block_random_access_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/linear_solver.h" +#include "ceres/schur_eliminator.h" +#include "ceres/suitesparse.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class BlockSparseMatrixBase; + +// Base class for Schur complement based linear least squares +// solvers. It assumes that the input linear system Ax = b can be +// partitioned into +// +// E y + F z = b +// +// Where x = [y;z] is a partition of the variables. The paritioning +// of the variables is such that, E'E is a block diagonal +// matrix. Further, the rows of A are ordered so that for every +// variable block in y, all the rows containing that variable block +// occur as a vertically contiguous block. i.e the matrix A looks like +// +// E F +// A = [ y1 0 0 0 | z1 0 0 0 z5] +// [ y1 0 0 0 | z1 z2 0 0 0] +// [ 0 y2 0 0 | 0 0 z3 0 0] +// [ 0 0 y3 0 | z1 z2 z3 z4 z5] +// [ 0 0 y3 0 | z1 0 0 0 z5] +// [ 0 0 0 y4 | 0 0 0 0 z5] +// [ 0 0 0 y4 | 0 z2 0 0 0] +// [ 0 0 0 y4 | 0 0 0 0 0] +// [ 0 0 0 0 | z1 0 0 0 0] +// [ 0 0 0 0 | 0 0 z3 z4 z5] +// +// This structure should be reflected in the corresponding +// CompressedRowBlockStructure object associated with A. The linear +// system Ax = b should either be well posed or the array D below +// should be non-null and the diagonal matrix corresponding to it +// should be non-singular. +// +// SchurComplementSolver has two sub-classes. +// +// DenseSchurComplementSolver: For problems where the Schur complement +// matrix is small and dense, or if CHOLMOD/SuiteSparse is not +// installed. For structure from motion problems, this is solver can +// be used for problems with upto a few hundred cameras. +// +// SparseSchurComplementSolver: For problems where the Schur +// complement matrix is large and sparse. It requires that +// CHOLMOD/SuiteSparse be installed, as it uses CHOLMOD to find a +// sparse Cholesky factorization of the Schur complement. This solver +// can be used for solving structure from motion problems with tens of +// thousands of cameras, though depending on the exact sparsity +// structure, it maybe better to use an iterative solver. +// +// The two solvers can be instantiated by calling +// LinearSolver::CreateLinearSolver with LinearSolver::Options::type +// set to DENSE_SCHUR and SPARSE_SCHUR +// respectively. LinearSolver::Options::num_eliminate_blocks should be +// at least 1. +class SchurComplementSolver : public BlockSparseMatrixBaseSolver { + public: + explicit SchurComplementSolver(const LinearSolver::Options& options) + : options_(options) { + CHECK_GT(options.num_eliminate_blocks, 0); + } + + // LinearSolver methods + virtual ~SchurComplementSolver() {} + virtual LinearSolver::Summary SolveImpl( + BlockSparseMatrixBase* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x); + + protected: + const LinearSolver::Options& options() const { return options_; } + + const BlockRandomAccessMatrix* lhs() const { return lhs_.get(); } + void set_lhs(BlockRandomAccessMatrix* lhs) { lhs_.reset(lhs); } + const double* rhs() const { return rhs_.get(); } + void set_rhs(double* rhs) { rhs_.reset(rhs); } + + private: + virtual void InitStorage(const CompressedRowBlockStructure* bs) = 0; + virtual bool SolveReducedLinearSystem(double* solution) = 0; + + LinearSolver::Options options_; + + scoped_ptr eliminator_; + scoped_ptr lhs_; + scoped_array rhs_; + + DISALLOW_COPY_AND_ASSIGN(SchurComplementSolver); +}; + +// Dense Cholesky factorization based solver. +class DenseSchurComplementSolver : public SchurComplementSolver { + public: + explicit DenseSchurComplementSolver(const LinearSolver::Options& options) + : SchurComplementSolver(options) {} + virtual ~DenseSchurComplementSolver() {} + + private: + virtual void InitStorage(const CompressedRowBlockStructure* bs); + virtual bool SolveReducedLinearSystem(double* solution); + + DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver); +}; + +#ifndef CERES_NO_SUITESPARSE +// Sparse Cholesky factorization based solver. +class SparseSchurComplementSolver : public SchurComplementSolver { + public: + explicit SparseSchurComplementSolver(const LinearSolver::Options& options); + virtual ~SparseSchurComplementSolver(); + + private: + virtual void InitStorage(const CompressedRowBlockStructure* bs); + virtual bool SolveReducedLinearSystem(double* solution); + + + SuiteSparse ss_; + // Symbolic factorization of the reduced linear system. Precomputed + // once and reused if constant_sparsity_ is true. + cholmod_factor* symbolic_factor_; + DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver); +}; +#else // CERES_NO_SUITESPARSE +class SparseSchurComplementSolver : public SchurComplementSolver { + public: + explicit SparseSchurComplementSolver(const LinearSolver::Options& options) + : SchurComplementSolver(options) { + LOG(FATAL) << "SPARSE_SCHUR is not available. Please " + "build Ceres with SuiteSparse."; + } + + virtual ~SparseSchurComplementSolver() {} +}; +#endif // CERES_NO_SUITESPARSE + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc new file mode 100644 index 00000000000..44f5be3b4e9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc @@ -0,0 +1,141 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_template_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/linear_solver.h" +#include "ceres/schur_eliminator.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +SchurEliminatorBase* +SchurEliminatorBase::Create(const LinearSolver::Options& options) { +#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION + if ((options.row_block_size == 2) && + (options.e_block_size == 2) && + (options.f_block_size == 2)) { + return new SchurEliminator<2, 2, 2>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 2) && + (options.f_block_size == 3)) { + return new SchurEliminator<2, 2, 3>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 2) && + (options.f_block_size == 4)) { + return new SchurEliminator<2, 2, 4>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 2) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator<2, 2, Dynamic>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 3) && + (options.f_block_size == 3)) { + return new SchurEliminator<2, 3, 3>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 3) && + (options.f_block_size == 4)) { + return new SchurEliminator<2, 3, 4>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 3) && + (options.f_block_size == 9)) { + return new SchurEliminator<2, 3, 9>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 3) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator<2, 3, Dynamic>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 4) && + (options.f_block_size == 3)) { + return new SchurEliminator<2, 4, 3>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 4) && + (options.f_block_size == 4)) { + return new SchurEliminator<2, 4, 4>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 4) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator<2, 4, Dynamic>(options); + } + if ((options.row_block_size == 4) && + (options.e_block_size == 4) && + (options.f_block_size == 2)) { + return new SchurEliminator<4, 4, 2>(options); + } + if ((options.row_block_size == 4) && + (options.e_block_size == 4) && + (options.f_block_size == 3)) { + return new SchurEliminator<4, 4, 3>(options); + } + if ((options.row_block_size == 4) && + (options.e_block_size == 4) && + (options.f_block_size == 4)) { + return new SchurEliminator<4, 4, 4>(options); + } + if ((options.row_block_size == 4) && + (options.e_block_size == 4) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator<4, 4, Dynamic>(options); + } + if ((options.row_block_size == Dynamic) && + (options.e_block_size == Dynamic) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator(options); + } + +#endif + VLOG(1) << "Template specializations not found for <" + << options.row_block_size << "," + << options.e_block_size << "," + << options.f_block_size << ">"; + return new SchurEliminator(options); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h new file mode 100644 index 00000000000..c24fe435f54 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h @@ -0,0 +1,339 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_SCHUR_ELIMINATOR_H_ +#define CERES_INTERNAL_SCHUR_ELIMINATOR_H_ + +#include +#include +#include "ceres/mutex.h" +#include "ceres/block_random_access_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/linear_solver.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +// Classes implementing the SchurEliminatorBase interface implement +// variable elimination for linear least squares problems. Assuming +// that the input linear system Ax = b can be partitioned into +// +// E y + F z = b +// +// Where x = [y;z] is a partition of the variables. The paritioning +// of the variables is such that, E'E is a block diagonal matrix. Or +// in other words, the parameter blocks in E form an independent set +// of the of the graph implied by the block matrix A'A. Then, this +// class provides the functionality to compute the Schur complement +// system +// +// S z = r +// +// where +// +// S = F'F - F'E (E'E)^{-1} E'F and r = F'b - F'E(E'E)^(-1) E'b +// +// This is the Eliminate operation, i.e., construct the linear system +// obtained by eliminating the variables in E. +// +// The eliminator also provides the reverse functionality, i.e. given +// values for z it can back substitute for the values of y, by solving the +// linear system +// +// Ey = b - F z +// +// which is done by observing that +// +// y = (E'E)^(-1) [E'b - E'F z] +// +// The eliminator has a number of requirements. +// +// The rows of A are ordered so that for every variable block in y, +// all the rows containing that variable block occur as a vertically +// contiguous block. i.e the matrix A looks like +// +// E F chunk +// A = [ y1 0 0 0 | z1 0 0 0 z5] 1 +// [ y1 0 0 0 | z1 z2 0 0 0] 1 +// [ 0 y2 0 0 | 0 0 z3 0 0] 2 +// [ 0 0 y3 0 | z1 z2 z3 z4 z5] 3 +// [ 0 0 y3 0 | z1 0 0 0 z5] 3 +// [ 0 0 0 y4 | 0 0 0 0 z5] 4 +// [ 0 0 0 y4 | 0 z2 0 0 0] 4 +// [ 0 0 0 y4 | 0 0 0 0 0] 4 +// [ 0 0 0 0 | z1 0 0 0 0] non chunk blocks +// [ 0 0 0 0 | 0 0 z3 z4 z5] non chunk blocks +// +// This structure should be reflected in the corresponding +// CompressedRowBlockStructure object associated with A. The linear +// system Ax = b should either be well posed or the array D below +// should be non-null and the diagonal matrix corresponding to it +// should be non-singular. For simplicity of exposition only the case +// with a null D is described. +// +// The usual way to do the elimination is as follows. Starting with +// +// E y + F z = b +// +// we can form the normal equations, +// +// E'E y + E'F z = E'b +// F'E y + F'F z = F'b +// +// multiplying both sides of the first equation by (E'E)^(-1) and then +// by F'E we get +// +// F'E y + F'E (E'E)^(-1) E'F z = F'E (E'E)^(-1) E'b +// F'E y + F'F z = F'b +// +// now subtracting the two equations we get +// +// [FF' - F'E (E'E)^(-1) E'F] z = F'b - F'E(E'E)^(-1) E'b +// +// Instead of forming the normal equations and operating on them as +// general sparse matrices, the algorithm here deals with one +// parameter block in y at a time. The rows corresponding to a single +// parameter block yi are known as a chunk, and the algorithm operates +// on one chunk at a time. The mathematics remains the same since the +// reduced linear system can be shown to be the sum of the reduced +// linear systems for each chunk. This can be seen by observing two +// things. +// +// 1. E'E is a block diagonal matrix. +// +// 2. When E'F is computed, only the terms within a single chunk +// interact, i.e for y1 column blocks when transposed and multiplied +// with F, the only non-zero contribution comes from the blocks in +// chunk1. +// +// Thus, the reduced linear system +// +// FF' - F'E (E'E)^(-1) E'F +// +// can be re-written as +// +// sum_k F_k F_k' - F_k'E_k (E_k'E_k)^(-1) E_k' F_k +// +// Where the sum is over chunks and E_k'E_k is dense matrix of size y1 +// x y1. +// +// Advanced usage. Uptil now it has been assumed that the user would +// be interested in all of the Schur Complement S. However, it is also +// possible to use this eliminator to obtain an arbitrary submatrix of +// the full Schur complement. When the eliminator is generating the +// blocks of S, it asks the RandomAccessBlockMatrix instance passed to +// it if it has storage for that block. If it does, the eliminator +// computes/updates it, if not it is skipped. This is useful when one +// is interested in constructing a preconditioner based on the Schur +// Complement, e.g., computing the block diagonal of S so that it can +// be used as a preconditioner for an Iterative Substructuring based +// solver [See Agarwal et al, Bundle Adjustment in the Large, ECCV +// 2008 for an example of such use]. +// +// Example usage: Please see schur_complement_solver.cc +class SchurEliminatorBase { + public: + virtual ~SchurEliminatorBase() {} + + // Initialize the eliminator. It is the user's responsibilty to call + // this function before calling Eliminate or BackSubstitute. It is + // also the caller's responsibilty to ensure that the + // CompressedRowBlockStructure object passed to this method is the + // same one (or is equivalent to) the one associated with the + // BlockSparseMatrixBase objects below. + virtual void Init(int num_eliminate_blocks, + const CompressedRowBlockStructure* bs) = 0; + + // Compute the Schur complement system from the augmented linear + // least squares problem [A;D] x = [b;0]. The left hand side and the + // right hand side of the reduced linear system are returned in lhs + // and rhs respectively. + // + // It is the caller's responsibility to construct and initialize + // lhs. Depending upon the structure of the lhs object passed here, + // the full or a submatrix of the Schur complement will be computed. + // + // Since the Schur complement is a symmetric matrix, only the upper + // triangular part of the Schur complement is computed. + virtual void Eliminate(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + BlockRandomAccessMatrix* lhs, + double* rhs) = 0; + + // Given values for the variables z in the F block of A, solve for + // the optimal values of the variables y corresponding to the E + // block in A. + virtual void BackSubstitute(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + const double* z, + double* y) = 0; + // Factory + static SchurEliminatorBase* Create(const LinearSolver::Options& options); +}; + +// Templated implementation of the SchurEliminatorBase interface. The +// templating is on the sizes of the row, e and f blocks sizes in the +// input matrix. In many problems, the sizes of one or more of these +// blocks are constant, in that case, its worth passing these +// parameters as template arguments so that they are visible to the +// compiler and can be used for compile time optimization of the low +// level linear algebra routines. +// +// This implementation is mulithreaded using OpenMP. The level of +// parallelism is controlled by LinearSolver::Options::num_threads. +template +class SchurEliminator : public SchurEliminatorBase { + public: + explicit SchurEliminator(const LinearSolver::Options& options) + : num_threads_(options.num_threads) { + } + + // SchurEliminatorBase Interface + virtual ~SchurEliminator(); + virtual void Init(int num_eliminate_blocks, + const CompressedRowBlockStructure* bs); + virtual void Eliminate(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + BlockRandomAccessMatrix* lhs, + double* rhs); + virtual void BackSubstitute(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + const double* z, + double* y); + + private: + // Chunk objects store combinatorial information needed to + // efficiently eliminate a whole chunk out of the least squares + // problem. Consider the first chunk in the example matrix above. + // + // [ y1 0 0 0 | z1 0 0 0 z5] + // [ y1 0 0 0 | z1 z2 0 0 0] + // + // One of the intermediate quantities that needs to be calculated is + // for each row the product of the y block transposed with the + // non-zero z block, and the sum of these blocks across rows. A + // temporary array "buffer_" is used for computing and storing them + // and the buffer_layout maps the indices of the z-blocks to + // position in the buffer_ array. The size of the chunk is the + // number of row blocks/residual blocks for the particular y block + // being considered. + // + // For the example chunk shown above, + // + // size = 2 + // + // The entries of buffer_layout will be filled in the following order. + // + // buffer_layout[z1] = 0 + // buffer_layout[z5] = y1 * z1 + // buffer_layout[z2] = y1 * z1 + y1 * z5 + typedef map BufferLayoutType; + struct Chunk { + Chunk() : size(0) {} + int size; + int start; + BufferLayoutType buffer_layout; + }; + + void ChunkDiagonalBlockAndGradient( + const Chunk& chunk, + const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + typename EigenTypes::Matrix* eet, + typename EigenTypes::Vector* g, + double* buffer, + BlockRandomAccessMatrix* lhs); + + void UpdateRhs(const Chunk& chunk, + const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + const Vector& inverse_ete_g, + double* rhs); + + void ChunkOuterProduct(const CompressedRowBlockStructure* bs, + const Matrix& inverse_eet, + const double* buffer, + const BufferLayoutType& buffer_layout, + BlockRandomAccessMatrix* lhs); + void EBlockRowOuterProduct(const BlockSparseMatrixBase* A, + int row_block_index, + BlockRandomAccessMatrix* lhs); + + + void NoEBlockRowsUpdate(const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + BlockRandomAccessMatrix* lhs, + double* rhs); + + void NoEBlockRowOuterProduct(const BlockSparseMatrixBase* A, + int row_block_index, + BlockRandomAccessMatrix* lhs); + + int num_eliminate_blocks_; + + // Block layout of the columns of the reduced linear system. Since + // the f blocks can be of varying size, this vector stores the + // position of each f block in the row/col of the reduced linear + // system. Thus lhs_row_layout_[i] is the row/col position of the + // i^th f block. + vector lhs_row_layout_; + + // Combinatorial structure of the chunks in A. For more information + // see the documentation of the Chunk object above. + vector chunks_; + + // Buffer to store the products of the y and z blocks generated + // during the elimination phase. + scoped_array buffer_; + int buffer_size_; + int num_threads_; + int uneliminated_row_begins_; + + // Locks for the blocks in the right hand side of the reduced linear + // system. + vector rhs_locks_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCHUR_ELIMINATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h new file mode 100644 index 00000000000..a388d005424 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h @@ -0,0 +1,702 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// TODO(sameeragarwal): row_block_counter can perhaps be replaced by +// Chunk::start ? + +#ifndef CERES_INTERNAL_SCHUR_ELIMINATOR_IMPL_H_ +#define CERES_INTERNAL_SCHUR_ELIMINATOR_IMPL_H_ + +#ifdef CERES_USE_OPENMP +#include +#endif + +// Eigen has an internal threshold switching between different matrix +// multiplication algorithms. In particular for matrices larger than +// EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD it uses a cache friendly +// matrix matrix product algorithm that has a higher setup cost. For +// matrix sizes close to this threshold, especially when the matrices +// are thin and long, the default choice may not be optimal. This is +// the case for us, as the default choice causes a 30% performance +// regression when we moved from Eigen2 to Eigen3. +#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 10 + +#include +#include +#include +#include "Eigen/Dense" +#include "ceres/block_random_access_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/map_util.h" +#include "ceres/schur_eliminator.h" +#include "ceres/stl_util.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +template +SchurEliminator::~SchurEliminator() { + STLDeleteElements(&rhs_locks_); +} + +template +void +SchurEliminator:: +Init(int num_eliminate_blocks, const CompressedRowBlockStructure* bs) { + CHECK_GT(num_eliminate_blocks, 0) + << "SchurComplementSolver cannot be initialized with " + << "num_eliminate_blocks = 0."; + + num_eliminate_blocks_ = num_eliminate_blocks; + + const int num_col_blocks = bs->cols.size(); + const int num_row_blocks = bs->rows.size(); + + buffer_size_ = 1; + chunks_.clear(); + lhs_row_layout_.clear(); + + int lhs_num_rows = 0; + // Add a map object for each block in the reduced linear system + // and build the row/column block structure of the reduced linear + // system. + lhs_row_layout_.resize(num_col_blocks - num_eliminate_blocks_); + for (int i = num_eliminate_blocks_; i < num_col_blocks; ++i) { + lhs_row_layout_[i - num_eliminate_blocks_] = lhs_num_rows; + lhs_num_rows += bs->cols[i].size; + } + + int r = 0; + // Iterate over the row blocks of A, and detect the chunks. The + // matrix should already have been ordered so that all rows + // containing the same y block are vertically contiguous. Along + // the way also compute the amount of space each chunk will need + // to perform the elimination. + while (r < num_row_blocks) { + const int chunk_block_id = bs->rows[r].cells.front().block_id; + if (chunk_block_id >= num_eliminate_blocks_) { + break; + } + + chunks_.push_back(Chunk()); + Chunk& chunk = chunks_.back(); + chunk.size = 0; + chunk.start = r; + int buffer_size = 0; + const int e_block_size = bs->cols[chunk_block_id].size; + + // Add to the chunk until the first block in the row is + // different than the one in the first row for the chunk. + while (r + chunk.size < num_row_blocks) { + const CompressedRow& row = bs->rows[r + chunk.size]; + if (row.cells.front().block_id != chunk_block_id) { + break; + } + + // Iterate over the blocks in the row, ignoring the first + // block since it is the one to be eliminated. + for (int c = 1; c < row.cells.size(); ++c) { + const Cell& cell = row.cells[c]; + if (InsertIfNotPresent( + &(chunk.buffer_layout), cell.block_id, buffer_size)) { + buffer_size += e_block_size * bs->cols[cell.block_id].size; + } + } + + buffer_size_ = max(buffer_size, buffer_size_); + ++chunk.size; + } + + CHECK_GT(chunk.size, 0); + r += chunk.size; + } + const Chunk& chunk = chunks_.back(); + + uneliminated_row_begins_ = chunk.start + chunk.size; + if (num_threads_ > 1) { + random_shuffle(chunks_.begin(), chunks_.end()); + } + + buffer_.reset(new double[buffer_size_ * num_threads_]); + + STLDeleteElements(&rhs_locks_); + rhs_locks_.resize(num_col_blocks - num_eliminate_blocks_); + for (int i = 0; i < num_col_blocks - num_eliminate_blocks_; ++i) { + rhs_locks_[i] = new Mutex; + } + + VLOG(1) << "Eliminator threads: " << num_threads_; +} + +template +void +SchurEliminator:: +Eliminate(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + BlockRandomAccessMatrix* lhs, + double* rhs) { + if (lhs->num_rows() > 0) { + lhs->SetZero(); + VectorRef(rhs, lhs->num_rows()).setZero(); + } + + const CompressedRowBlockStructure* bs = A->block_structure(); + const int num_col_blocks = bs->cols.size(); + + // Add the diagonal to the schur complement. + if (D != NULL) { +#pragma omp parallel for num_threads(num_threads_) schedule(dynamic) + for (int i = num_eliminate_blocks_; i < num_col_blocks; ++i) { + const int block_id = i - num_eliminate_blocks_; + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block_id, block_id, + &r, &c, + &row_stride, &col_stride); + if (cell_info != NULL) { + const int block_size = bs->cols[i].size; + typename EigenTypes::ConstVectorRef + diag(D + bs->cols[i].position, block_size); + + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + m.block(r, c, block_size, block_size).diagonal() + += diag.array().square().matrix(); + } + } + } + + // Eliminate y blocks one chunk at a time. For each chunk,x3 + // compute the entries of the normal equations and the gradient + // vector block corresponding to the y block and then apply + // Gaussian elimination to them. The matrix ete stores the normal + // matrix corresponding to the block being eliminated and array + // buffer_ contains the non-zero blocks in the row corresponding + // to this y block in the normal equations. This computation is + // done in ChunkDiagonalBlockAndGradient. UpdateRhs then applies + // gaussian elimination to the rhs of the normal equations, + // updating the rhs of the reduced linear system by modifying rhs + // blocks for all the z blocks that share a row block/residual + // term with the y block. EliminateRowOuterProduct does the + // corresponding operation for the lhs of the reduced linear + // system. +#pragma omp parallel for num_threads(num_threads_) schedule(dynamic) + for (int i = 0; i < chunks_.size(); ++i) { +#ifdef CERES_USE_OPENMP + int thread_id = omp_get_thread_num(); +#else + int thread_id = 0; +#endif + double* buffer = buffer_.get() + thread_id * buffer_size_; + const Chunk& chunk = chunks_[i]; + const int e_block_id = bs->rows[chunk.start].cells.front().block_id; + const int e_block_size = bs->cols[e_block_id].size; + + VectorRef(buffer, buffer_size_).setZero(); + + typename EigenTypes::Matrix + ete(e_block_size, e_block_size); + + if (D != NULL) { + const typename EigenTypes::ConstVectorRef + diag(D + bs->cols[e_block_id].position, e_block_size); + ete = diag.array().square().matrix().asDiagonal(); + } else { + ete.setZero(); + } + + typename EigenTypes::Vector g(e_block_size); + g.setZero(); + + // We are going to be computing + // + // S += F'F - F'E(E'E)^{-1}E'F + // + // for each Chunk. The computation is broken down into a number of + // function calls as below. + + // Compute the outer product of the e_blocks with themselves (ete + // = E'E). Compute the product of the e_blocks with the + // corresonding f_blocks (buffer = E'F), the gradient of the terms + // in this chunk (g) and add the outer product of the f_blocks to + // Schur complement (S += F'F). + ChunkDiagonalBlockAndGradient( + chunk, A, b, chunk.start, &ete, &g, buffer, lhs); + + // Normally one wouldn't compute the inverse explicitly, but + // e_block_size will typically be a small number like 3, in + // which case its much faster to compute the inverse once and + // use it to multiply other matrices/vectors instead of doing a + // Solve call over and over again. + typename EigenTypes::Matrix inverse_ete = + ete + .template selfadjointView() + .ldlt() + .solve(Matrix::Identity(e_block_size, e_block_size)); + + // For the current chunk compute and update the rhs of the reduced + // linear system. + // + // rhs = F'b - F'E(E'E)^(-1) E'b + UpdateRhs(chunk, A, b, chunk.start, inverse_ete * g, rhs); + + // S -= F'E(E'E)^{-1}E'F + ChunkOuterProduct(bs, inverse_ete, buffer, chunk.buffer_layout, lhs); + } + + // For rows with no e_blocks, the schur complement update reduces to + // S += F'F. + NoEBlockRowsUpdate(A, b, uneliminated_row_begins_, lhs, rhs); +} + +template +void +SchurEliminator:: +BackSubstitute(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + const double* z, + double* y) { + const CompressedRowBlockStructure* bs = A->block_structure(); +#pragma omp parallel for num_threads(num_threads_) schedule(dynamic) + for (int i = 0; i < chunks_.size(); ++i) { + const Chunk& chunk = chunks_[i]; + const int e_block_id = bs->rows[chunk.start].cells.front().block_id; + const int e_block_size = bs->cols[e_block_id].size; + + typename EigenTypes::VectorRef y_block( + y + bs->cols[e_block_id].position, e_block_size); + + typename EigenTypes::Matrix + ete(e_block_size, e_block_size); + if (D != NULL) { + const typename EigenTypes::ConstVectorRef + diag(D + bs->cols[e_block_id].position, e_block_size); + ete = diag.array().square().matrix().asDiagonal(); + } else { + ete.setZero(); + } + + for (int j = 0; j < chunk.size; ++j) { + const CompressedRow& row = bs->rows[chunk.start + j]; + const double* row_values = A->RowBlockValues(chunk.start + j); + const Cell& e_cell = row.cells.front(); + DCHECK_EQ(e_block_id, e_cell.block_id); + const typename EigenTypes::ConstMatrixRef + e_block(row_values + e_cell.position, + row.block.size, + e_block_size); + + typename EigenTypes::Vector + sj = + typename EigenTypes::ConstVectorRef + (b + bs->rows[chunk.start + j].block.position, + row.block.size); + + for (int c = 1; c < row.cells.size(); ++c) { + const int f_block_id = row.cells[c].block_id; + const int f_block_size = bs->cols[f_block_id].size; + const typename EigenTypes::ConstMatrixRef + f_block(row_values + row.cells[c].position, + row.block.size, f_block_size); + const int r_block = f_block_id - num_eliminate_blocks_; + + sj -= f_block * + typename EigenTypes::ConstVectorRef + (z + lhs_row_layout_[r_block], f_block_size); + } + + y_block += e_block.transpose() * sj; + ete.template selfadjointView() + .rankUpdate(e_block.transpose(), 1.0); + } + + y_block = + ete + .template selfadjointView() + .ldlt() + .solve(y_block); + } +} + +// Update the rhs of the reduced linear system. Compute +// +// F'b - F'E(E'E)^(-1) E'b +template +void +SchurEliminator:: +UpdateRhs(const Chunk& chunk, + const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + const Vector& inverse_ete_g, + double* rhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + const int e_block_size = inverse_ete_g.rows(); + int b_pos = bs->rows[row_block_counter].block.position; + for (int j = 0; j < chunk.size; ++j) { + const CompressedRow& row = bs->rows[row_block_counter + j]; + const double *row_values = A->RowBlockValues(row_block_counter + j); + const Cell& e_cell = row.cells.front(); + + const typename EigenTypes::ConstMatrixRef + e_block(row_values + e_cell.position, + row.block.size, + e_block_size); + + const typename EigenTypes::Vector + sj = + typename EigenTypes::ConstVectorRef + (b + b_pos, row.block.size) - e_block * (inverse_ete_g); + + for (int c = 1; c < row.cells.size(); ++c) { + const int block_id = row.cells[c].block_id; + const int block_size = bs->cols[block_id].size; + const typename EigenTypes::ConstMatrixRef + b(row_values + row.cells[c].position, + row.block.size, block_size); + + const int block = block_id - num_eliminate_blocks_; + MutexLock l(rhs_locks_[block]); + typename EigenTypes::VectorRef + (rhs + lhs_row_layout_[block], block_size).noalias() + += b.transpose() * sj; + } + b_pos += row.block.size; + } +} + +// Given a Chunk - set of rows with the same e_block, e.g. in the +// following Chunk with two rows. +// +// E F +// [ y11 0 0 0 | z11 0 0 0 z51] +// [ y12 0 0 0 | z12 z22 0 0 0] +// +// this function computes twp matrices. The diagonal block matrix +// +// ete = y11 * y11' + y12 * y12' +// +// and the off diagonal blocks in the Guass Newton Hessian. +// +// buffer = [y11'(z11 + z12), y12' * z22, y11' * z51] +// +// which are zero compressed versions of the block sparse matrices E'E +// and E'F. +// +// and the gradient of the e_block, E'b. +template +void +SchurEliminator:: +ChunkDiagonalBlockAndGradient( + const Chunk& chunk, + const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + typename EigenTypes::Matrix* ete, + typename EigenTypes::Vector* g, + double* buffer, + BlockRandomAccessMatrix* lhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + + int b_pos = bs->rows[row_block_counter].block.position; + const int e_block_size = ete->rows(); + + // Iterate over the rows in this chunk, for each row, compute the + // contribution of its F blocks to the Schur complement, the + // contribution of its E block to the matrix EE' (ete), and the + // corresponding block in the gradient vector. + for (int j = 0; j < chunk.size; ++j) { + const CompressedRow& row = bs->rows[row_block_counter + j]; + const double *row_values = A->RowBlockValues(row_block_counter + j); + + if (row.cells.size() > 1) { + EBlockRowOuterProduct(A, row_block_counter + j, lhs); + } + + // Extract the e_block, ETE += E_i' E_i + const Cell& e_cell = row.cells.front(); + const typename EigenTypes::ConstMatrixRef + e_block(row_values + e_cell.position, + row.block.size, + e_block_size); + + ete->template selfadjointView() + .rankUpdate(e_block.transpose(), 1.0); + + // g += E_i' b_i + g->noalias() += e_block.transpose() * + typename EigenTypes::ConstVectorRef + (b + b_pos, row.block.size); + + // buffer = E'F. This computation is done by iterating over the + // f_blocks for each row in the chunk. + for (int c = 1; c < row.cells.size(); ++c) { + const int f_block_id = row.cells[c].block_id; + const int f_block_size = bs->cols[f_block_id].size; + const typename EigenTypes::ConstMatrixRef + f_block(row_values + row.cells[c].position, + row.block.size, f_block_size); + + double* buffer_ptr = + buffer + FindOrDie(chunk.buffer_layout, f_block_id); + + typename EigenTypes::MatrixRef + (buffer_ptr, e_block_size, f_block_size).noalias() + += e_block.transpose() * f_block; + } + b_pos += row.block.size; + } +} + +// Compute the outer product F'E(E'E)^{-1}E'F and subtract it from the +// Schur complement matrix, i.e +// +// S -= F'E(E'E)^{-1}E'F. +template +void +SchurEliminator:: +ChunkOuterProduct(const CompressedRowBlockStructure* bs, + const Matrix& inverse_ete, + const double* buffer, + const BufferLayoutType& buffer_layout, + BlockRandomAccessMatrix* lhs) { + // This is the most computationally expensive part of this + // code. Profiling experiments reveal that the bottleneck is not the + // computation of the right-hand matrix product, but memory + // references to the left hand side. + const int e_block_size = inverse_ete.rows(); + BufferLayoutType::const_iterator it1 = buffer_layout.begin(); + // S(i,j) -= bi' * ete^{-1} b_j + for (; it1 != buffer_layout.end(); ++it1) { + const int block1 = it1->first - num_eliminate_blocks_; + const int block1_size = bs->cols[it1->first].size; + + const typename EigenTypes::ConstMatrixRef + b1(buffer + it1->second, e_block_size, block1_size); + const typename EigenTypes::Matrix + b1_transpose_inverse_ete = b1.transpose() * inverse_ete; + + BufferLayoutType::const_iterator it2 = it1; + for (; it2 != buffer_layout.end(); ++it2) { + const int block2 = it2->first - num_eliminate_blocks_; + + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block2, + &r, &c, + &row_stride, &col_stride); + if (cell_info == NULL) { + continue; + } + + const int block2_size = bs->cols[it2->first].size; + const typename EigenTypes::ConstMatrixRef + b2(buffer + it2->second, e_block_size, block2_size); + + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + + // We explicitly construct a block object here instead of using + // m.block(), as m.block() variant of the constructor does not + // allow mixing of template sizing and runtime sizing parameters + // like the Matrix class does. + Eigen::Block + block(m, r, c, block1_size, block2_size); + block.noalias() -= b1_transpose_inverse_ete * b2; + } + } +} + +// For rows with no e_blocks, the schur complement update reduces to S +// += F'F. This function iterates over the rows of A with no e_block, +// and calls NoEBlockRowOuterProduct on each row. +template +void +SchurEliminator:: +NoEBlockRowsUpdate(const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + BlockRandomAccessMatrix* lhs, + double* rhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + for (; row_block_counter < bs->rows.size(); ++row_block_counter) { + const CompressedRow& row = bs->rows[row_block_counter]; + const double *row_values = A->RowBlockValues(row_block_counter); + for (int c = 0; c < row.cells.size(); ++c) { + const int block_id = row.cells[c].block_id; + const int block_size = bs->cols[block_id].size; + const int block = block_id - num_eliminate_blocks_; + VectorRef(rhs + lhs_row_layout_[block], block_size).noalias() + += (ConstMatrixRef(row_values + row.cells[c].position, + row.block.size, block_size).transpose() * + ConstVectorRef(b + row.block.position, row.block.size)); + } + NoEBlockRowOuterProduct(A, row_block_counter, lhs); + } +} + + +// A row r of A, which has no e_blocks gets added to the Schur +// Complement as S += r r'. This function is responsible for computing +// the contribution of a single row r to the Schur complement. It is +// very similar in structure to EBlockRowOuterProduct except for +// one difference. It does not use any of the template +// parameters. This is because the algorithm used for detecting the +// static structure of the matrix A only pays attention to rows with +// e_blocks. This is becase rows without e_blocks are rare and +// typically arise from regularization terms in the original +// optimization problem, and have a very different structure than the +// rows with e_blocks. Including them in the static structure +// detection will lead to most template parameters being set to +// dynamic. Since the number of rows without e_blocks is small, the +// lack of templating is not an issue. +template +void +SchurEliminator:: +NoEBlockRowOuterProduct(const BlockSparseMatrixBase* A, + int row_block_index, + BlockRandomAccessMatrix* lhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + const CompressedRow& row = bs->rows[row_block_index]; + const double *row_values = A->RowBlockValues(row_block_index); + for (int i = 0; i < row.cells.size(); ++i) { + const int block1 = row.cells[i].block_id - num_eliminate_blocks_; + DCHECK_GE(block1, 0); + + const int block1_size = bs->cols[row.cells[i].block_id].size; + const ConstMatrixRef b1(row_values + row.cells[i].position, + row.block.size, block1_size); + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block1, + &r, &c, + &row_stride, &col_stride); + if (cell_info != NULL) { + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + m.block(r, c, block1_size, block1_size) + .selfadjointView() + .rankUpdate(b1.transpose(), 1.0); + } + + for (int j = i + 1; j < row.cells.size(); ++j) { + const int block2 = row.cells[j].block_id - num_eliminate_blocks_; + DCHECK_GE(block2, 0); + DCHECK_LT(block1, block2); + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block2, + &r, &c, + &row_stride, &col_stride); + if (cell_info == NULL) { + continue; + } + + const int block2_size = bs->cols[row.cells[j].block_id].size; + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + m.block(r, c, block1_size, block2_size).noalias() += + b1.transpose() * ConstMatrixRef(row_values + row.cells[j].position, + row.block.size, + block2_size); + } + } +} + +// For a row with an e_block, compute the contribition S += F'F. This +// function has the same structure as NoEBlockRowOuterProduct, except +// that this function uses the template parameters. +template +void +SchurEliminator:: +EBlockRowOuterProduct(const BlockSparseMatrixBase* A, + int row_block_index, + BlockRandomAccessMatrix* lhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + const CompressedRow& row = bs->rows[row_block_index]; + const double *row_values = A->RowBlockValues(row_block_index); + for (int i = 1; i < row.cells.size(); ++i) { + const int block1 = row.cells[i].block_id - num_eliminate_blocks_; + DCHECK_GE(block1, 0); + + const int block1_size = bs->cols[row.cells[i].block_id].size; + const typename EigenTypes::ConstMatrixRef + b1(row_values + row.cells[i].position, + row.block.size, block1_size); + { + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block1, + &r, &c, + &row_stride, &col_stride); + if (cell_info == NULL) { + continue; + } + + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + + Eigen::Block + block(m, r, c, block1_size, block1_size); + block.template selfadjointView() + .rankUpdate(b1.transpose(), 1.0); + } + + for (int j = i + 1; j < row.cells.size(); ++j) { + const int block2 = row.cells[j].block_id - num_eliminate_blocks_; + DCHECK_GE(block2, 0); + DCHECK_LT(block1, block2); + const int block2_size = bs->cols[row.cells[j].block_id].size; + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block2, + &r, &c, + &row_stride, &col_stride); + if (cell_info == NULL) { + continue; + } + + const typename EigenTypes::ConstMatrixRef + b2(row_values + row.cells[j].position, + row.block.size, + block2_size); + + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + Eigen::Block + block(m, r, c, block1_size, block2_size); + block.noalias() += b1.transpose() * b2; + } + } +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCHUR_ELIMINATOR_IMPL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc new file mode 100644 index 00000000000..c4fc1da3c2f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc @@ -0,0 +1,113 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/schur_ordering.h" + +#include +#include "ceres/graph.h" +#include "ceres/graph_algorithms.h" +#include "ceres/map_util.h" +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/internal/scoped_ptr.h" + +CERES_HASH_NAMESPACE_START + +// Allow us to hash pointers as if they were int's +template<> struct hash< ::ceres::internal::ParameterBlock*> { + size_t operator()(::ceres::internal::ParameterBlock* x) const { + return reinterpret_cast(x); + } +}; + +CERES_HASH_NAMESPACE_END + +namespace ceres { +namespace internal { + +int ComputeSchurOrdering(const Program& program, + vector* ordering) { + CHECK_NOTNULL(ordering)->clear(); + + scoped_ptr > graph( + CHECK_NOTNULL(CreateHessianGraph(program))); + int independent_set_size = + IndependentSetOrdering(*graph, ordering); + const vector& parameter_blocks = program.parameter_blocks(); + + // Add the excluded blocks to back of the ordering vector. + for (int i = 0; i < parameter_blocks.size(); ++i) { + ParameterBlock* parameter_block = parameter_blocks[i]; + if (parameter_block->IsConstant()) { + ordering->push_back(parameter_block); + } + } + + return independent_set_size; +} + +Graph* +CreateHessianGraph(const Program& program) { + Graph* graph = new Graph; + const vector& parameter_blocks = program.parameter_blocks(); + for (int i = 0; i < parameter_blocks.size(); ++i) { + ParameterBlock* parameter_block = parameter_blocks[i]; + if (!parameter_block->IsConstant()) { + graph->AddVertex(parameter_block); + } + } + + const vector& residual_blocks = program.residual_blocks(); + for (int i = 0; i < residual_blocks.size(); ++i) { + const ResidualBlock* residual_block = residual_blocks[i]; + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + ParameterBlock* const* parameter_blocks = + residual_block->parameter_blocks(); + for (int j = 0; j < num_parameter_blocks; ++j) { + if (parameter_blocks[j]->IsConstant()) { + continue; + } + + for (int k = j + 1; k < num_parameter_blocks; ++k) { + if (parameter_blocks[k]->IsConstant()) { + continue; + } + + graph->AddEdge(parameter_blocks[j], parameter_blocks[k]); + } + } + } + + return graph; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h new file mode 100644 index 00000000000..1f9a4ff354f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h @@ -0,0 +1,74 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Compute a parameter block ordering for use with the Schur +// complement based algorithms. + +#ifndef CERES_INTERNAL_SCHUR_ORDERING_H_ +#define CERES_INTERNAL_SCHUR_ORDERING_H_ + +#include +#include "ceres/graph.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class Program; +class ParameterBlock; + +// Uses an approximate independent set ordering to order the parameter +// blocks of a problem so that it is suitable for use with Schur +// complement based solvers. The output variable ordering contains an +// ordering of the parameter blocks and the return value is size of +// the independent set or the number of e_blocks (see +// schur_complement_solver.h for an explanation). Constant parameters +// are added to the end. +// +// The ordering vector has the structure +// +// ordering = [independent set, +// complement of the independent set, +// fixed blocks] +int ComputeSchurOrdering(const Program& program, + vector* ordering); + + +// Builds a graph on the parameter blocks of a Problem, whose +// structure reflects the sparsity structure of the Hessian. Each +// vertex corresponds to a parameter block in the Problem except for +// parameter blocks that are marked constant. An edge connects two +// parameter blocks, if they co-occur in a residual block. +Graph* CreateHessianGraph(const Program& program); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCHUR_ORDERING_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.cc b/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.cc new file mode 100644 index 00000000000..6f0ceefd87d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.cc @@ -0,0 +1,78 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/scratch_evaluate_preparer.h" + +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" + +namespace ceres { +namespace internal { + +ScratchEvaluatePreparer* ScratchEvaluatePreparer::Create( + const Program &program, + int num_threads) { + ScratchEvaluatePreparer* preparers = new ScratchEvaluatePreparer[num_threads]; + int max_derivatives_per_residual_block = + program.MaxDerivativesPerResidualBlock(); + for (int i = 0; i < num_threads; i++) { + preparers[i].Init(max_derivatives_per_residual_block); + } + return preparers; +} + +void ScratchEvaluatePreparer::Init(int max_derivatives_per_residual_block) { + jacobian_scratch_.reset( + new double[max_derivatives_per_residual_block]); +} + +// Point the jacobian blocks into the scratch area of this evaluate preparer. +void ScratchEvaluatePreparer::Prepare(const ResidualBlock* residual_block, + int /* residual_block_index */, + SparseMatrix* /* jacobian */, + double** jacobians) { + double* jacobian_block_cursor = jacobian_scratch_.get(); + int num_residuals = residual_block->NumResiduals(); + int num_parameter_blocks = residual_block->NumParameterBlocks(); + for (int j = 0; j < num_parameter_blocks; ++j) { + const ParameterBlock* parameter_block = + residual_block->parameter_blocks()[j]; + if (parameter_block->IsConstant()) { + jacobians[j] = NULL; + } else { + jacobians[j] = jacobian_block_cursor; + jacobian_block_cursor += num_residuals * parameter_block->LocalSize(); + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.h b/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.h new file mode 100644 index 00000000000..6b127081976 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.h @@ -0,0 +1,69 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A scratch evaluate preparer provides temporary storage for the jacobians that +// are created when running user-provided cost functions. The evaluator takes +// care to avoid evaluating the jacobian for fixed parameters. + +#ifndef CERES_INTERNAL_SCRATCH_EVALUATE_PREPARER_H_ +#define CERES_INTERNAL_SCRATCH_EVALUATE_PREPARER_H_ + +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +class Program; +class ResidualBlock; +class SparseMatrix; + +class ScratchEvaluatePreparer { + public: + // Create num_threads ScratchEvaluatePreparers. + static ScratchEvaluatePreparer* Create(const Program &program, + int num_threads); + + // EvaluatePreparer interface + void Init(int max_derivatives_per_residual_block); + void Prepare(const ResidualBlock* residual_block, + int residual_block_index, + SparseMatrix* jacobian, + double** jacobians); + + private: + // Scratch space for the jacobians; each jacobian is packed one after another. + // There is enough scratch to hold all the jacobians for the largest residual. + scoped_array jacobian_scratch_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCRATCH_EVALUATE_PREPARER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver.cc b/extern/libmv/third_party/ceres/internal/ceres/solver.cc new file mode 100644 index 00000000000..77f04d1d918 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/solver.cc @@ -0,0 +1,230 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/solver.h" + +#include +#include "ceres/levenberg_marquardt.h" +#include "ceres/program.h" +#include "ceres/solver_impl.h" +#include "ceres/stringprintf.h" +#include "ceres/problem.h" + +namespace ceres { + +Solver::~Solver() {} + +// TODO(sameeragarwal): The timing code here should use a sub-second +// timer. +void Solver::Solve(const Solver::Options& options, + Problem* problem, + Solver::Summary* summary) { + time_t start_time_seconds = time(NULL); + internal::SolverImpl::Solve(options, problem, summary); + summary->total_time_in_seconds = time(NULL) - start_time_seconds; + summary->preprocessor_time_in_seconds = + summary->total_time_in_seconds - summary->minimizer_time_in_seconds; +} + +void Solve(const Solver::Options& options, + Problem* problem, + Solver::Summary* summary) { + time_t start_time_seconds = time(NULL); + internal::SolverImpl::Solve(options, problem, summary); + summary->total_time_in_seconds = time(NULL) - start_time_seconds; + summary->preprocessor_time_in_seconds = + summary->total_time_in_seconds - summary->minimizer_time_in_seconds; +} + +Solver::Summary::Summary() + // Invalid values for most fields, to ensure that we are not + // accidentally reporting default values. + : termination_type(DID_NOT_RUN), + initial_cost(-1.0), + final_cost(-1.0), + fixed_cost(-1.0), + num_successful_steps(-1), + num_unsuccessful_steps(-1), + preprocessor_time_in_seconds(-1.0), + minimizer_time_in_seconds(-1.0), + total_time_in_seconds(-1.0), + num_parameter_blocks(-1), + num_parameters(-1), + num_residual_blocks(-1), + num_residuals(-1), + num_parameter_blocks_reduced(-1), + num_parameters_reduced(-1), + num_residual_blocks_reduced(-1), + num_residuals_reduced(-1), + num_eliminate_blocks_given(-1), + num_eliminate_blocks_used(-1), + num_threads_given(-1), + num_threads_used(-1), + num_linear_solver_threads_given(-1), + num_linear_solver_threads_used(-1), + linear_solver_type_given(SPARSE_NORMAL_CHOLESKY), + linear_solver_type_used(SPARSE_NORMAL_CHOLESKY), + preconditioner_type(IDENTITY), + ordering_type(NATURAL) { +} + +string Solver::Summary::BriefReport() const { + string report = "Ceres Solver Report: "; + if (termination_type == DID_NOT_RUN) { + CHECK(!error.empty()) + << "Solver terminated with DID_NOT_RUN but the solver did not " + << "return a reason. This is a Ceres error. Please report this " + << "to the Ceres team"; + return report + "Termination: DID_NOT_RUN, because " + error; + } + + internal::StringAppendF(&report, "Iterations: %d", + num_successful_steps + num_unsuccessful_steps); + internal::StringAppendF(&report, ", Initial cost: %e", initial_cost); + + // If the solver failed or was aborted, then the final_cost has no + // meaning. + if (termination_type != NUMERICAL_FAILURE && + termination_type != USER_ABORT) { + internal::StringAppendF(&report, ", Final cost: %e", final_cost); + } + + internal::StringAppendF(&report, ", Termination: %s.", + SolverTerminationTypeToString(termination_type)); + return report; +}; + +string Solver::Summary::FullReport() const { + string report = + "\n" + "Ceres Solver Report\n" + "-------------------\n"; + + if (termination_type == DID_NOT_RUN) { + internal::StringAppendF(&report, " Original\n"); + internal::StringAppendF(&report, "Parameter blocks % 10d\n", + num_parameter_blocks); + internal::StringAppendF(&report, "Parameters % 10d\n", + num_parameters); + internal::StringAppendF(&report, "Residual blocks % 10d\n", + num_residual_blocks); + internal::StringAppendF(&report, "Residual % 10d\n\n", + num_residuals); + } else { + internal::StringAppendF(&report, "%45s %21s\n", "Original", "Reduced"); + internal::StringAppendF(&report, "Parameter blocks % 25d% 25d\n", + num_parameter_blocks, num_parameter_blocks_reduced); + internal::StringAppendF(&report, "Parameters % 25d% 25d\n", + num_parameters, num_parameters_reduced); + internal::StringAppendF(&report, "Residual blocks % 25d% 25d\n", + num_residual_blocks, num_residual_blocks_reduced); + internal::StringAppendF(&report, "Residual % 25d% 25d\n\n", + num_residuals, num_residuals_reduced); + } + + internal::StringAppendF(&report, "%45s %21s\n", "Given", "Used"); + internal::StringAppendF(&report, "Linear solver %25s%25s\n", + LinearSolverTypeToString(linear_solver_type_given), + LinearSolverTypeToString(linear_solver_type_used)); + + if (linear_solver_type_given == CGNR || + linear_solver_type_given == ITERATIVE_SCHUR) { + internal::StringAppendF(&report, "Preconditioner %25s%25s\n", + PreconditionerTypeToString(preconditioner_type), + PreconditionerTypeToString(preconditioner_type)); + } else { + internal::StringAppendF(&report, "Preconditioner %25s%25s\n", + "N/A", "N/A"); + } + + internal::StringAppendF(&report, "Ordering %25s%25s\n", + OrderingTypeToString(ordering_type), + OrderingTypeToString(ordering_type)); + + if (IsSchurType(linear_solver_type_given)) { + if (ordering_type == SCHUR) { + internal::StringAppendF(&report, "num_eliminate_blocks%25s% 25d\n", + "N/A", + num_eliminate_blocks_used); + } else { + internal::StringAppendF(&report, "num_eliminate_blocks% 25d% 25d\n", + num_eliminate_blocks_given, + num_eliminate_blocks_used); + } + } + + internal::StringAppendF(&report, "Threads: % 25d% 25d\n", + num_threads_given, num_threads_used); + internal::StringAppendF(&report, "Linear Solver Threads:% 23d% 25d\n", + num_linear_solver_threads_given, + num_linear_solver_threads_used); + + + if (termination_type == DID_NOT_RUN) { + CHECK(!error.empty()) + << "Solver terminated with DID_NOT_RUN but the solver did not " + << "return a reason. This is a Ceres error. Please report this " + << "to the Ceres team"; + internal::StringAppendF(&report, "Termination: %20s\n", + "DID_NOT_RUN"); + internal::StringAppendF(&report, "Reason: %s\n", error.c_str()); + return report; + } + + internal::StringAppendF(&report, "\nCost:\n"); + internal::StringAppendF(&report, "Initial % 30e\n", initial_cost); + if (termination_type != NUMERICAL_FAILURE && termination_type != USER_ABORT) { + internal::StringAppendF(&report, "Final % 30e\n", final_cost); + internal::StringAppendF(&report, "Change % 30e\n", + initial_cost - final_cost); + } + + internal::StringAppendF(&report, "\nNumber of iterations:\n"); + internal::StringAppendF(&report, "Successful % 20d\n", + num_successful_steps); + internal::StringAppendF(&report, "Unsuccessful % 20d\n", + num_unsuccessful_steps); + internal::StringAppendF(&report, "Total % 20d\n", + num_successful_steps + num_unsuccessful_steps); + internal::StringAppendF(&report, "\nTime (in seconds):\n"); + internal::StringAppendF(&report, "Preprocessor % 25e\n", + preprocessor_time_in_seconds); + internal::StringAppendF(&report, "Minimizer % 25e\n", + minimizer_time_in_seconds); + internal::StringAppendF(&report, "Total % 25e\n", + total_time_in_seconds); + + internal::StringAppendF(&report, "Termination: %25s\n", + SolverTerminationTypeToString(termination_type)); + return report; +}; + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc new file mode 100644 index 00000000000..ed07d9dc6d7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc @@ -0,0 +1,693 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/solver_impl.h" + +#include // NOLINT +#include +#include "ceres/evaluator.h" +#include "ceres/gradient_checking_cost_function.h" +#include "ceres/levenberg_marquardt.h" +#include "ceres/linear_solver.h" +#include "ceres/map_util.h" +#include "ceres/minimizer.h" +#include "ceres/parameter_block.h" +#include "ceres/problem_impl.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/schur_ordering.h" +#include "ceres/stringprintf.h" +#include "ceres/iteration_callback.h" +#include "ceres/problem.h" + +namespace ceres { +namespace internal { +namespace { + +void EvaluateCostAndResiduals(ProblemImpl* problem_impl, + double* cost, + vector* residuals) { + CHECK_NOTNULL(cost); + Program* program = CHECK_NOTNULL(problem_impl)->mutable_program(); + if (residuals != NULL) { + residuals->resize(program->NumResiduals()); + program->Evaluate(cost, &(*residuals)[0]); + } else { + program->Evaluate(cost, NULL); + } +} + +// Callback for updating the user's parameter blocks. Updates are only +// done if the step is successful. +class StateUpdatingCallback : public IterationCallback { + public: + StateUpdatingCallback(Program* program, double* parameters) + : program_(program), parameters_(parameters) {} + + CallbackReturnType operator()(const IterationSummary& summary) { + if (summary.step_is_successful) { + program_->StateVectorToParameterBlocks(parameters_); + program_->CopyParameterBlockStateToUserState(); + } + return SOLVER_CONTINUE; + } + + private: + Program* program_; + double* parameters_; +}; + +// Callback for logging the state of the minimizer to STDERR or STDOUT +// depending on the user's preferences and logging level. +class LoggingCallback : public IterationCallback { + public: + explicit LoggingCallback(bool log_to_stdout) + : log_to_stdout_(log_to_stdout) {} + + ~LoggingCallback() {} + + CallbackReturnType operator()(const IterationSummary& summary) { + const char* kReportRowFormat = + "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e " + "rho:% 3.2e mu:% 3.2e li:% 3d"; + string output = StringPrintf(kReportRowFormat, + summary.iteration, + summary.cost, + summary.cost_change, + summary.gradient_max_norm, + summary.step_norm, + summary.relative_decrease, + summary.mu, + summary.linear_solver_iterations); + if (log_to_stdout_) { + cout << output << endl; + } else { + VLOG(1) << output; + } + return SOLVER_CONTINUE; + } + + private: + const bool log_to_stdout_; +}; + +} // namespace + +void SolverImpl::Minimize(const Solver::Options& options, + Program* program, + Evaluator* evaluator, + LinearSolver* linear_solver, + double* initial_parameters, + double* final_parameters, + Solver::Summary* summary) { + Minimizer::Options minimizer_options(options); + + LoggingCallback logging_callback(options.minimizer_progress_to_stdout); + if (options.logging_type != SILENT) { + minimizer_options.callbacks.push_back(&logging_callback); + } + + StateUpdatingCallback updating_callback(program, initial_parameters); + if (options.update_state_every_iteration) { + minimizer_options.callbacks.push_back(&updating_callback); + } + + LevenbergMarquardt levenberg_marquardt; + + time_t start_minimizer_time_seconds = time(NULL); + levenberg_marquardt.Minimize(minimizer_options, + evaluator, + linear_solver, + initial_parameters, + final_parameters, + summary); + summary->minimizer_time_in_seconds = + time(NULL) - start_minimizer_time_seconds; +} + +void SolverImpl::Solve(const Solver::Options& original_options, + Problem* problem, + Solver::Summary* summary) { + Solver::Options options(original_options); + +#ifndef CERES_USE_OPENMP + if (options.num_threads > 1) { + LOG(WARNING) + << "OpenMP support is not compiled into this binary; " + << "only options.num_threads=1 is supported. Switching" + << "to single threaded mode."; + options.num_threads = 1; + } + if (options.num_linear_solver_threads > 1) { + LOG(WARNING) + << "OpenMP support is not compiled into this binary; " + << "only options.num_linear_solver_threads=1 is supported. Switching" + << "to single threaded mode."; + options.num_linear_solver_threads = 1; + } +#endif + + // Reset the summary object to its default values; + *CHECK_NOTNULL(summary) = Solver::Summary(); + summary->linear_solver_type_given = options.linear_solver_type; + summary->num_eliminate_blocks_given = original_options.num_eliminate_blocks; + summary->num_threads_given = original_options.num_threads; + summary->num_linear_solver_threads_given = + original_options.num_linear_solver_threads; + summary->ordering_type = original_options.ordering_type; + + ProblemImpl* problem_impl = CHECK_NOTNULL(problem)->problem_impl_.get(); + + summary->num_parameter_blocks = problem_impl->NumParameterBlocks(); + summary->num_parameters = problem_impl->NumParameters(); + summary->num_residual_blocks = problem_impl->NumResidualBlocks(); + summary->num_residuals = problem_impl->NumResiduals(); + + summary->num_threads_used = options.num_threads; + + // Evaluate the initial cost and residual vector (if needed). The + // initial cost needs to be computed on the original unpreprocessed + // problem, as it is used to determine the value of the "fixed" part + // of the objective function after the problem has undergone + // reduction. Also the initial residuals are in the order in which + // the user added the ResidualBlocks to the optimization problem. + EvaluateCostAndResiduals(problem_impl, + &summary->initial_cost, + options.return_initial_residuals + ? &summary->initial_residuals + : NULL); + + // If the user requests gradient checking, construct a new + // ProblemImpl by wrapping the CostFunctions of problem_impl inside + // GradientCheckingCostFunction and replacing problem_impl with + // gradient_checking_problem_impl. + scoped_ptr gradient_checking_problem_impl; + if (options.check_gradients) { + VLOG(1) << "Checking Gradients"; + gradient_checking_problem_impl.reset( + CreateGradientCheckingProblemImpl( + problem_impl, + options.numeric_derivative_relative_step_size, + options.gradient_check_relative_precision)); + + // From here on, problem_impl will point to the GradientChecking version. + problem_impl = gradient_checking_problem_impl.get(); + } + + // Create the three objects needed to minimize: the transformed program, the + // evaluator, and the linear solver. + + scoped_ptr reduced_program( + CreateReducedProgram(&options, problem_impl, &summary->error)); + if (reduced_program == NULL) { + return; + } + + summary->num_parameter_blocks_reduced = reduced_program->NumParameterBlocks(); + summary->num_parameters_reduced = reduced_program->NumParameters(); + summary->num_residual_blocks_reduced = reduced_program->NumResidualBlocks(); + summary->num_residuals_reduced = reduced_program->NumResiduals(); + + scoped_ptr + linear_solver(CreateLinearSolver(&options, &summary->error)); + summary->linear_solver_type_used = options.linear_solver_type; + summary->preconditioner_type = options.preconditioner_type; + summary->num_eliminate_blocks_used = options.num_eliminate_blocks; + summary->num_linear_solver_threads_used = options.num_linear_solver_threads; + + if (linear_solver == NULL) { + return; + } + + if (!MaybeReorderResidualBlocks(options, + reduced_program.get(), + &summary->error)) { + return; + } + + scoped_ptr evaluator( + CreateEvaluator(options, reduced_program.get(), &summary->error)); + if (evaluator == NULL) { + return; + } + + // The optimizer works on contiguous parameter vectors; allocate some. + Vector initial_parameters(reduced_program->NumParameters()); + Vector optimized_parameters(reduced_program->NumParameters()); + + // Collect the discontiguous parameters into a contiguous state vector. + reduced_program->ParameterBlocksToStateVector(&initial_parameters[0]); + + // Run the optimization. + Minimize(options, + reduced_program.get(), + evaluator.get(), + linear_solver.get(), + initial_parameters.data(), + optimized_parameters.data(), + summary); + + // If the user aborted mid-optimization or the optimization + // terminated because of a numerical failure, then return without + // updating user state. + if (summary->termination_type == USER_ABORT || + summary->termination_type == NUMERICAL_FAILURE) { + return; + } + + // Push the contiguous optimized parameters back to the user's parameters. + reduced_program->StateVectorToParameterBlocks(&optimized_parameters[0]); + reduced_program->CopyParameterBlockStateToUserState(); + + // Return the final cost and residuals for the original problem. + EvaluateCostAndResiduals(problem->problem_impl_.get(), + &summary->final_cost, + options.return_final_residuals + ? &summary->final_residuals + : NULL); + + // Stick a fork in it, we're done. + return; +} + +// Strips varying parameters and residuals, maintaining order, and updating +// num_eliminate_blocks. +bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program, + int* num_eliminate_blocks, + string* error) { + int original_num_eliminate_blocks = *num_eliminate_blocks; + vector* parameter_blocks = + program->mutable_parameter_blocks(); + + // Mark all the parameters as unused. Abuse the index member of the parameter + // blocks for the marking. + for (int i = 0; i < parameter_blocks->size(); ++i) { + (*parameter_blocks)[i]->set_index(-1); + } + + // Filter out residual that have all-constant parameters, and mark all the + // parameter blocks that appear in residuals. + { + vector* residual_blocks = + program->mutable_residual_blocks(); + int j = 0; + for (int i = 0; i < residual_blocks->size(); ++i) { + ResidualBlock* residual_block = (*residual_blocks)[i]; + int num_parameter_blocks = residual_block->NumParameterBlocks(); + + // Determine if the residual block is fixed, and also mark varying + // parameters that appear in the residual block. + bool all_constant = true; + for (int k = 0; k < num_parameter_blocks; k++) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[k]; + if (!parameter_block->IsConstant()) { + all_constant = false; + parameter_block->set_index(1); + } + } + + if (!all_constant) { + (*residual_blocks)[j++] = (*residual_blocks)[i]; + } + } + residual_blocks->resize(j); + } + + // Filter out unused or fixed parameter blocks, and update + // num_eliminate_blocks as necessary. + { + vector* parameter_blocks = + program->mutable_parameter_blocks(); + int j = 0; + for (int i = 0; i < parameter_blocks->size(); ++i) { + ParameterBlock* parameter_block = (*parameter_blocks)[i]; + if (parameter_block->index() == 1) { + (*parameter_blocks)[j++] = parameter_block; + } else if (i < original_num_eliminate_blocks) { + (*num_eliminate_blocks)--; + } + } + parameter_blocks->resize(j); + } + + CHECK(((program->NumResidualBlocks() == 0) && + (program->NumParameterBlocks() == 0)) || + ((program->NumResidualBlocks() != 0) && + (program->NumParameterBlocks() != 0))) + << "Congratulations, you found a bug in Ceres. Please report it."; + return true; +} + +Program* SolverImpl::CreateReducedProgram(Solver::Options* options, + ProblemImpl* problem_impl, + string* error) { + Program* original_program = problem_impl->mutable_program(); + scoped_ptr transformed_program(new Program(*original_program)); + + if (options->ordering_type == USER && + !ApplyUserOrdering(*problem_impl, + options->ordering, + transformed_program.get(), + error)) { + return NULL; + } + + if (options->ordering_type == SCHUR && options->num_eliminate_blocks != 0) { + *error = "Can't specify SCHUR ordering and num_eliminate_blocks " + "at the same time; SCHUR ordering determines " + "num_eliminate_blocks automatically."; + return NULL; + } + + if (options->ordering_type == SCHUR && options->ordering.size() != 0) { + *error = "Can't specify SCHUR ordering type and the ordering " + "vector at the same time; SCHUR ordering determines " + "a suitable parameter ordering automatically."; + return NULL; + } + + int num_eliminate_blocks = options->num_eliminate_blocks; + + if (!RemoveFixedBlocksFromProgram(transformed_program.get(), + &num_eliminate_blocks, + error)) { + return NULL; + } + + if (transformed_program->NumParameterBlocks() == 0) { + LOG(WARNING) << "No varying parameter blocks to optimize; " + << "bailing early."; + return transformed_program.release(); + } + + if (options->ordering_type == SCHUR) { + vector schur_ordering; + num_eliminate_blocks = ComputeSchurOrdering(*transformed_program, + &schur_ordering); + CHECK_EQ(schur_ordering.size(), transformed_program->NumParameterBlocks()) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Replace the transformed program's ordering with the schur ordering. + swap(*transformed_program->mutable_parameter_blocks(), schur_ordering); + } + options->num_eliminate_blocks = num_eliminate_blocks; + CHECK_GE(options->num_eliminate_blocks, 0) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Since the transformed program is the "active" program, and it is mutated, + // update the parameter offsets and indices. + transformed_program->SetParameterOffsetsAndIndex(); + return transformed_program.release(); +} + +LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options, + string* error) { +#ifdef CERES_NO_SUITESPARSE + if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY) { + *error = "Can't use SPARSE_NORMAL_CHOLESKY because SuiteSparse was not " + "enabled when Ceres was built."; + return NULL; + } +#endif // CERES_NO_SUITESPARSE + + if (options->linear_solver_max_num_iterations <= 0) { + *error = "Solver::Options::linear_solver_max_num_iterations is 0."; + return NULL; + } + if (options->linear_solver_min_num_iterations <= 0) { + *error = "Solver::Options::linear_solver_min_num_iterations is 0."; + return NULL; + } + if (options->linear_solver_min_num_iterations > + options->linear_solver_max_num_iterations) { + *error = "Solver::Options::linear_solver_min_num_iterations > " + "Solver::Options::linear_solver_max_num_iterations."; + return NULL; + } + + LinearSolver::Options linear_solver_options; + linear_solver_options.constant_sparsity = true; + linear_solver_options.min_num_iterations = + options->linear_solver_min_num_iterations; + linear_solver_options.max_num_iterations = + options->linear_solver_max_num_iterations; + linear_solver_options.type = options->linear_solver_type; + linear_solver_options.preconditioner_type = options->preconditioner_type; + +#ifdef CERES_NO_SUITESPARSE + if (linear_solver_options.preconditioner_type == SCHUR_JACOBI) { + *error = "SCHUR_JACOBI preconditioner not suppored. Please build Ceres " + "with SuiteSparse support"; + return NULL; + } + + if (linear_solver_options.preconditioner_type == CLUSTER_JACOBI) { + *error = "CLUSTER_JACOBI preconditioner not suppored. Please build Ceres " + "with SuiteSparse support"; + return NULL; + } + + if (linear_solver_options.preconditioner_type == CLUSTER_TRIDIAGONAL) { + *error = "CLUSTER_TRIDIAGONAL preconditioner not suppored. Please build " + "Ceres with SuiteSparse support"; + return NULL; + } +#endif + + linear_solver_options.num_threads = options->num_linear_solver_threads; + linear_solver_options.num_eliminate_blocks = + options->num_eliminate_blocks; + + if ((linear_solver_options.num_eliminate_blocks == 0) && + IsSchurType(linear_solver_options.type)) { +#ifndef CERES_NO_SUITESPARSE + LOG(INFO) << "No elimination block remaining " + << "switching to SPARSE_NORMAL_CHOLESKY."; + linear_solver_options.type = SPARSE_NORMAL_CHOLESKY; +#else + LOG(INFO) << "No elimination block remaining switching to DENSE_QR."; + linear_solver_options.type = DENSE_QR; +#endif // CERES_NO_SUITESPARSE + } + +#ifdef CERES_NO_SUITESPARSE + if (linear_solver_options.type == SPARSE_SCHUR) { + *error = "Can't use SPARSE_SCHUR because SuiteSparse was not " + "enabled when Ceres was built."; + return NULL; + } +#endif // CERES_NO_SUITESPARSE + + // The matrix used for storing the dense Schur complement has a + // single lock guarding the whole matrix. Running the + // SchurComplementSolver with multiple threads leads to maximum + // contention and slowdown. If the problem is large enough to + // benefit from a multithreaded schur eliminator, you should be + // using a SPARSE_SCHUR solver anyways. + if ((linear_solver_options.num_threads > 1) && + (linear_solver_options.type == DENSE_SCHUR)) { + LOG(WARNING) << "Warning: Solver::Options::num_linear_solver_threads = " + << options->num_linear_solver_threads + << " with DENSE_SCHUR will result in poor performance; " + << "switching to single-threaded."; + linear_solver_options.num_threads = 1; + } + + options->linear_solver_type = linear_solver_options.type; + options->num_linear_solver_threads = linear_solver_options.num_threads; + + return LinearSolver::Create(linear_solver_options); +} + +bool SolverImpl::ApplyUserOrdering(const ProblemImpl& problem_impl, + vector& ordering, + Program* program, + string* error) { + if (ordering.size() != program->NumParameterBlocks()) { + *error = StringPrintf("User specified ordering does not have the same " + "number of parameters as the problem. The problem" + "has %d blocks while the ordering has %ld blocks.", + program->NumParameterBlocks(), + ordering.size()); + return false; + } + + // Ensure that there are no duplicates in the user's ordering. + { + vector ordering_copy(ordering); + sort(ordering_copy.begin(), ordering_copy.end()); + if (unique(ordering_copy.begin(), ordering_copy.end()) + != ordering_copy.end()) { + *error = "User specified ordering contains duplicates."; + return false; + } + } + + vector* parameter_blocks = + program->mutable_parameter_blocks(); + + fill(parameter_blocks->begin(), + parameter_blocks->end(), + static_cast(NULL)); + + const ProblemImpl::ParameterMap& parameter_map = problem_impl.parameter_map(); + for (int i = 0; i < ordering.size(); ++i) { + ProblemImpl::ParameterMap::const_iterator it = + parameter_map.find(ordering[i]); + if (it == parameter_map.end()) { + *error = StringPrintf("User specified ordering contains a pointer " + "to a double that is not a parameter block in the " + "problem. The invalid double is at position %d " + " in options.ordering.", i); + return false; + } + (*parameter_blocks)[i] = it->second; + } + return true; +} + +// Find the minimum index of any parameter block to the given residual. +// Parameter blocks that have indices greater than num_eliminate_blocks are +// considered to have an index equal to num_eliminate_blocks. +int MinParameterBlock(const ResidualBlock* residual_block, + int num_eliminate_blocks) { + int min_parameter_block_position = num_eliminate_blocks; + for (int i = 0; i < residual_block->NumParameterBlocks(); ++i) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[i]; + DCHECK_NE(parameter_block->index(), -1) + << "Did you forget to call Program::SetParameterOffsetsAndIndex()?"; + min_parameter_block_position = std::min(parameter_block->index(), + min_parameter_block_position); + } + return min_parameter_block_position; +} + +// Reorder the residuals for program, if necessary, so that the residuals +// involving each E block occur together. This is a necessary condition for the +// Schur eliminator, which works on these "row blocks" in the jacobian. +bool SolverImpl::MaybeReorderResidualBlocks(const Solver::Options& options, + Program* program, + string* error) { + // Only Schur types require the lexicographic reordering. + if (!IsSchurType(options.linear_solver_type)) { + return true; + } + + CHECK_NE(0, options.num_eliminate_blocks) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Create a histogram of the number of residuals for each E block. There is an + // extra bucket at the end to catch all non-eliminated F blocks. + vector residual_blocks_per_e_block(options.num_eliminate_blocks + 1); + vector* residual_blocks = program->mutable_residual_blocks(); + vector min_position_per_residual(residual_blocks->size()); + for (int i = 0; i < residual_blocks->size(); ++i) { + ResidualBlock* residual_block = (*residual_blocks)[i]; + int position = MinParameterBlock(residual_block, + options.num_eliminate_blocks); + min_position_per_residual[i] = position; + DCHECK_LE(position, options.num_eliminate_blocks); + residual_blocks_per_e_block[position]++; + } + + // Run a cumulative sum on the histogram, to obtain offsets to the start of + // each histogram bucket (where each bucket is for the residuals for that + // E-block). + vector offsets(options.num_eliminate_blocks + 1); + std::partial_sum(residual_blocks_per_e_block.begin(), + residual_blocks_per_e_block.end(), + offsets.begin()); + CHECK_EQ(offsets.back(), residual_blocks->size()) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + CHECK(find(residual_blocks_per_e_block.begin(), + residual_blocks_per_e_block.end() - 1, 0) != + residual_blocks_per_e_block.end()) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Fill in each bucket with the residual blocks for its corresponding E block. + // Each bucket is individually filled from the back of the bucket to the front + // of the bucket. The filling order among the buckets is dictated by the + // residual blocks. This loop uses the offsets as counters; subtracting one + // from each offset as a residual block is placed in the bucket. When the + // filling is finished, the offset pointerts should have shifted down one + // entry (this is verified below). + vector reordered_residual_blocks( + (*residual_blocks).size(), static_cast(NULL)); + for (int i = 0; i < residual_blocks->size(); ++i) { + int bucket = min_position_per_residual[i]; + + // Decrement the cursor, which should now point at the next empty position. + offsets[bucket]--; + + // Sanity. + CHECK(reordered_residual_blocks[offsets[bucket]] == NULL) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + reordered_residual_blocks[offsets[bucket]] = (*residual_blocks)[i]; + } + + // Sanity check #1: The difference in bucket offsets should match the + // histogram sizes. + for (int i = 0; i < options.num_eliminate_blocks; ++i) { + CHECK_EQ(residual_blocks_per_e_block[i], offsets[i + 1] - offsets[i]) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + } + // Sanity check #2: No NULL's left behind. + for (int i = 0; i < reordered_residual_blocks.size(); ++i) { + CHECK(reordered_residual_blocks[i] != NULL) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + } + + // Now that the residuals are collected by E block, swap them in place. + swap(*program->mutable_residual_blocks(), reordered_residual_blocks); + return true; +} + +Evaluator* SolverImpl::CreateEvaluator(const Solver::Options& options, + Program* program, + string* error) { + Evaluator::Options evaluator_options; + evaluator_options.linear_solver_type = options.linear_solver_type; + evaluator_options.num_eliminate_blocks = options.num_eliminate_blocks; + evaluator_options.num_threads = options.num_threads; + return Evaluator::Create(evaluator_options, program, error); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h new file mode 100644 index 00000000000..957ebcc65df --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h @@ -0,0 +1,111 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_SOLVER_IMPL_H_ +#define CERES_INTERNAL_SOLVER_IMPL_H_ + +#include "ceres/solver.h" + +namespace ceres { +namespace internal { + +class Evaluator; +class LinearSolver; +class ProblemImpl; +class Program; + +class SolverImpl { + public: + // Mirrors the interface in solver.h, but exposes implementation + // details for testing internally. + static void Solve(const Solver::Options& options, + Problem* problem, + Solver::Summary* summary); + + // Create the transformed Program, which has all the fixed blocks + // and residuals eliminated, and in the case of automatic schur + // ordering, has the E blocks first in the resulting program, with + // options.num_eliminate_blocks set appropriately. + static Program* CreateReducedProgram(Solver::Options* options, + ProblemImpl* problem_impl, + string* error); + + // Create the appropriate linear solver, taking into account any + // config changes decided by CreateTransformedProgram(). The + // selected linear solver, which may be different from what the user + // selected; consider the case that the remaining elimininated + // blocks is zero after removing fixed blocks. + static LinearSolver* CreateLinearSolver(Solver::Options* options, + string* error); + + // Reorder the parameter blocks in program using the vector + // ordering. A return value of true indicates success and false + // indicates an error was encountered whose cause is logged to + // LOG(ERROR). + static bool ApplyUserOrdering(const ProblemImpl& problem_impl, + vector& ordering, + Program* program, + string* error); + + // Reorder the residuals for program, if necessary, so that the + // residuals involving each E block occur together. This is a + // necessary condition for the Schur eliminator, which works on + // these "row blocks" in the jacobian. + static bool MaybeReorderResidualBlocks(const Solver::Options& options, + Program* program, + string* error); + + // Create the appropriate evaluator for the transformed program. + static Evaluator* CreateEvaluator(const Solver::Options& options, + Program* program, + string* error); + + // Run the minimization for the given evaluator and configuration. + static void Minimize(const Solver::Options &options, + Program* program, + Evaluator* evaluator, + LinearSolver* linear_solver, + double* initial_parameters, + double* final_parameters, + Solver::Summary* summary); + + // Remove the fixed or unused parameter blocks and residuals + // depending only on fixed parameters from the problem. Also updates + // num_eliminate_blocks, since removed parameters changes the point + // at which the eliminated blocks is valid. + static bool RemoveFixedBlocksFromProgram(Program* program, + int* num_eliminate_blocks, + string* error); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SOLVER_IMPL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.cc new file mode 100644 index 00000000000..55336fd3130 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.cc @@ -0,0 +1,40 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/sparse_matrix.h" + +namespace ceres { +namespace internal { + +SparseMatrix::~SparseMatrix() { +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h new file mode 100644 index 00000000000..962b803dd87 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h @@ -0,0 +1,108 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Interface definition for sparse matrices. + +#ifndef CERES_INTERNAL_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_SPARSE_MATRIX_H_ + +#include "ceres/linear_operator.h" +#include "ceres/internal/eigen.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; + +// This class defines the interface for storing and manipulating +// sparse matrices. The key property that differentiates different +// sparse matrices is how they are organized in memory and how the +// information about the sparsity structure of the matrix is +// stored. This has significant implications for linear solvers +// operating on these matrices. +// +// To deal with the different kinds of layouts, we will assume that a +// sparse matrix will have a two part representation. A values array +// that will be used to store the entries of the sparse matrix and +// some sort of a layout object that tells the user the sparsity +// structure and layout of the values array. For example in case of +// the TripletSparseMatrix, this information is carried in the rows +// and cols arrays and for the BlockSparseMatrix, this information is +// carried in the CompressedRowBlockStructure object. +// +// This interface deliberately does not contain any information about +// the structure of the sparse matrix as that seems to be highly +// matrix type dependent and we are at this stage unable to come up +// with an efficient high level interface that spans multiple sparse +// matrix types. +class SparseMatrix : public LinearOperator { + public: + virtual ~SparseMatrix(); + + // y += Ax; + virtual void RightMultiply(const double* x, double* y) const = 0; + // y += A'x; + virtual void LeftMultiply(const double* x, double* y) const = 0; + + // In MATLAB notation sum(A.*A, 1) + virtual void SquaredColumnNorm(double* x) const = 0; + // A = A * diag(scale) + virtual void ScaleColumns(const double* scale) = 0; + + // A = 0. A->num_nonzeros() == 0 is true after this call. The + // sparsity pattern is preserved. + virtual void SetZero() = 0; + + // Resize and populate dense_matrix with a dense version of the + // sparse matrix. + virtual void ToDenseMatrix(Matrix* dense_matrix) const = 0; + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + // Dump the sparse matrix to a proto. Destroys the contents of proto. + virtual void ToProto(SparseMatrixProto *proto) const = 0; +#endif + + // Accessors for the values array that stores the entries of the + // sparse matrix. The exact interpreptation of the values of this + // array depends on the particular kind of SparseMatrix being + // accessed. + virtual double* mutable_values() = 0; + virtual const double* values() const = 0; + + virtual int num_rows() const = 0; + virtual int num_cols() const = 0; + virtual int num_nonzeros() const = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc new file mode 100644 index 00000000000..59222dc374d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc @@ -0,0 +1,129 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_NO_SUITESPARSE + +#include "ceres/sparse_normal_cholesky_solver.h" + +#include +#include +#include +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/linear_solver.h" +#include "ceres/suitesparse.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +SparseNormalCholeskySolver::SparseNormalCholeskySolver( + const LinearSolver::Options& options) + : options_(options), symbolic_factor_(NULL) {} + +SparseNormalCholeskySolver::~SparseNormalCholeskySolver() { + if (symbolic_factor_ != NULL) { + ss_.Free(symbolic_factor_); + symbolic_factor_ = NULL; + } +} + +LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double * x) { + const time_t start_time = time(NULL); + const int num_cols = A->num_cols(); + + LinearSolver::Summary summary; + Vector Atb = Vector::Zero(num_cols); + A->LeftMultiply(b, Atb.data()); + + if (per_solve_options.D != NULL) { + // Temporarily append a diagonal block to the A matrix, but undo it before + // returning the matrix to the user. + CompressedRowSparseMatrix D(per_solve_options.D, num_cols); + A->AppendRows(D); + } + + VectorRef(x, num_cols).setZero(); + + scoped_ptr lhs(ss_.CreateSparseMatrixTransposeView(A)); + CHECK_NOTNULL(lhs.get()); + + cholmod_dense* rhs = ss_.CreateDenseVector(Atb.data(), num_cols, num_cols); + const time_t init_time = time(NULL); + + if (symbolic_factor_ == NULL) { + symbolic_factor_ = CHECK_NOTNULL(ss_.AnalyzeCholesky(lhs.get())); + } + + const time_t symbolic_time = time(NULL); + + cholmod_dense* sol = ss_.SolveCholesky(lhs.get(), symbolic_factor_, rhs); + const time_t solve_time = time(NULL); + + ss_.Free(rhs); + rhs = NULL; + + if (per_solve_options.D != NULL) { + A->DeleteRows(num_cols); + } + + if (!options_.constant_sparsity) { + ss_.Free(symbolic_factor_); + symbolic_factor_ = NULL; + } + + summary.num_iterations = 1; + if (sol != NULL) { + memcpy(x, sol->x, num_cols * sizeof(*x)); + + ss_.Free(sol); + sol = NULL; + summary.termination_type = TOLERANCE; + } + + const time_t cleanup_time = time(NULL); + VLOG(2) << "time (sec) total: " << cleanup_time - start_time + << " init: " << init_time - start_time + << " symbolic: " << symbolic_time - init_time + << " solve: " << solve_time - symbolic_time + << " cleanup: " << cleanup_time - solve_time; + return summary; +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_SUITESPARSE diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h new file mode 100644 index 00000000000..ce1d6d285be --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h @@ -0,0 +1,77 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// A solver for sparse linear least squares problem based on solving +// the normal equations via a sparse cholesky factorization. + +#ifndef CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ +#define CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ + +#ifndef CERES_NO_SUITESPARSE + +#include "cholmod.h" +#include "cholmod_core.h" +#include "ceres/linear_solver.h" +#include "ceres/suitesparse.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +class CompressedRowSparseMatrix; + +// Solves the normal equations (A'A + D'D) x = A'b, using the CHOLMOD sparse +// cholesky solver. +class SparseNormalCholeskySolver : public CompressedRowSparseMatrixSolver { + public: + explicit SparseNormalCholeskySolver(const LinearSolver::Options& options); + virtual ~SparseNormalCholeskySolver(); + + private: + virtual LinearSolver::Summary SolveImpl( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& options, + double* x); + + const LinearSolver::Options options_; + SuiteSparse ss_; + + // Cached factorization + cholmod_factor* symbolic_factor_; + DISALLOW_COPY_AND_ASSIGN(SparseNormalCholeskySolver); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_SUITESPARSE + +#endif // CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/split.cc b/extern/libmv/third_party/ceres/internal/ceres/split.cc new file mode 100644 index 00000000000..4fa1bd468b9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/split.cc @@ -0,0 +1,115 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include +#include +#include +#include "ceres/internal/port.h" + +namespace ceres { + +// If we know how much to allocate for a vector of strings, we can allocate the +// vector only once and directly to the right size. This saves in +// between 33-66 % of memory space needed for the result, and runs faster in the +// microbenchmarks. +// +// The reserve is only implemented for the single character delim. +// +// The implementation for counting is cut-and-pasted from +// SplitStringToIteratorUsing. I could have written my own counting iterator, +// and use the existing template function, but probably this is more clear and +// more sure to get optimized to reasonable code. +static int CalculateReserveForVector(const string& full, const char* delim) { + int count = 0; + if (delim[0] != '\0' && delim[1] == '\0') { + // Optimize the common case where delim is a single character. + char c = delim[0]; + const char* p = full.data(); + const char* end = p + full.size(); + while (p != end) { + if (*p == c) { // This could be optimized with hasless(v,1) trick. + ++p; + } else { + while (++p != end && *p != c) { + // Skip to the next occurence of the delimiter. + } + ++count; + } + } + } + return count; +} + +template +static inline +void SplitStringToIteratorUsing(const StringType& full, + const char* delim, + ITR& result) { + // Optimize the common case where delim is a single character. + if (delim[0] != '\0' && delim[1] == '\0') { + char c = delim[0]; + const char* p = full.data(); + const char* end = p + full.size(); + while (p != end) { + if (*p == c) { + ++p; + } else { + const char* start = p; + while (++p != end && *p != c) { + // Skip to the next occurence of the delimiter. + } + *result++ = StringType(start, p - start); + } + } + return; + } + + string::size_type begin_index, end_index; + begin_index = full.find_first_not_of(delim); + while (begin_index != string::npos) { + end_index = full.find_first_of(delim, begin_index); + if (end_index == string::npos) { + *result++ = full.substr(begin_index); + return; + } + *result++ = full.substr(begin_index, (end_index - begin_index)); + begin_index = full.find_first_not_of(delim, end_index); + } +} + +void SplitStringUsing(const string& full, + const char* delim, + vector* result) { + result->reserve(result->size() + CalculateReserveForVector(full, delim)); + back_insert_iterator< vector > it(*result); + SplitStringToIteratorUsing(full, delim, it); +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/stl_util.h b/extern/libmv/third_party/ceres/internal/ceres/stl_util.h new file mode 100644 index 00000000000..a1a19e8b3ce --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/stl_util.h @@ -0,0 +1,75 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_STL_UTIL_H_ +#define CERES_INTERNAL_STL_UTIL_H_ + +namespace ceres { + +// STLDeleteContainerPointers() +// For a range within a container of pointers, calls delete +// (non-array version) on these pointers. +// NOTE: for these three functions, we could just implement a DeleteObject +// functor and then call for_each() on the range and functor, but this +// requires us to pull in all of algorithm.h, which seems expensive. +// For hash_[multi]set, it is important that this deletes behind the iterator +// because the hash_set may call the hash function on the iterator when it is +// advanced, which could result in the hash function trying to deference a +// stale pointer. +template +void STLDeleteContainerPointers(ForwardIterator begin, + ForwardIterator end) { + while (begin != end) { + ForwardIterator temp = begin; + ++begin; + delete *temp; + } +} + +// STLDeleteElements() deletes all the elements in an STL container and clears +// the container. This function is suitable for use with a vector, set, +// hash_set, or any other STL container which defines sensible begin(), end(), +// and clear() methods. +// +// If container is NULL, this function is a no-op. +// +// As an alternative to calling STLDeleteElements() directly, consider +// ElementDeleter (defined below), which ensures that your container's elements +// are deleted when the ElementDeleter goes out of scope. +template +void STLDeleteElements(T *container) { + if (!container) return; + STLDeleteContainerPointers(container->begin(), container->end()); + container->clear(); +} + +} // namespace ceres + +#endif // CERES_INTERNAL_STL_UTIL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc new file mode 100644 index 00000000000..c0f35225bc3 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc @@ -0,0 +1,126 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat + +#include +#include // For va_list and related operations +#include // MSVC requires this for _vsnprintf +#include +#include + +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +#ifdef _MSC_VER +enum { IS_COMPILER_MSVC = 1 }; +#define va_copy(d,s) ((d) = (s)) +#else +enum { IS_COMPILER_MSVC = 0 }; +#endif + +void StringAppendV(string* dst, const char* format, va_list ap) { + // First try with a small fixed size buffer + char space[1024]; + + // It's possible for methods that use a va_list to invalidate + // the data in it upon use. The fix is to make a copy + // of the structure before using it and use that copy instead. + va_list backup_ap; + va_copy(backup_ap, ap); + int result = vsnprintf(space, sizeof(space), format, backup_ap); + va_end(backup_ap); + + if (result < sizeof(space)) { + if (result >= 0) { + // Normal case -- everything fit. + dst->append(space, result); + return; + } + + if (IS_COMPILER_MSVC) { + // Error or MSVC running out of space. MSVC 8.0 and higher + // can be asked about space needed with the special idiom below: + va_copy(backup_ap, ap); + result = vsnprintf(NULL, 0, format, backup_ap); + va_end(backup_ap); + } + + if (result < 0) { + // Just an error. + return; + } + } + + // Increase the buffer size to the size requested by vsnprintf, + // plus one for the closing \0. + int length = result+1; + char* buf = new char[length]; + + // Restore the va_list before we use it again + va_copy(backup_ap, ap); + result = vsnprintf(buf, length, format, backup_ap); + va_end(backup_ap); + + if (result >= 0 && result < length) { + // It fit + dst->append(buf, result); + } + delete[] buf; +} + + +string StringPrintf(const char* format, ...) { + va_list ap; + va_start(ap, format); + string result; + StringAppendV(&result, format, ap); + va_end(ap); + return result; +} + +const string& SStringPrintf(string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + dst->clear(); + StringAppendV(dst, format, ap); + va_end(ap); + return *dst; +} + +void StringAppendF(string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + StringAppendV(dst, format, ap); + va_end(ap); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h new file mode 100644 index 00000000000..30b974e7ae5 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h @@ -0,0 +1,89 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat +// +// Printf variants that place their output in a C++ string. +// +// Usage: +// string result = StringPrintf("%d %s\n", 10, "hello"); +// SStringPrintf(&result, "%d %s\n", 10, "hello"); +// StringAppendF(&result, "%d %s\n", 20, "there"); + +#ifndef CERES_INTERNAL_STRINGPRINTF_H_ +#define CERES_INTERNAL_STRINGPRINTF_H_ + +#include +#include + +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +#if (defined(__GNUC__) || defined(__clang__)) +// Tell the compiler to do printf format string checking if the compiler +// supports it; see the 'format' attribute in +// . +// +// N.B.: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +#define PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__ (__printf__, string_index, first_to_check))) +#define SCANF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__ (__scanf__, string_index, first_to_check))) +#else +#define PRINTF_ATTRIBUTE(string_index, first_to_check) +#endif + +// Return a C++ string. +extern string StringPrintf(const char* format, ...) + // Tell the compiler to do printf format string checking. + PRINTF_ATTRIBUTE(1,2); + +// Store result into a supplied string and return it. +extern const string& SStringPrintf(string* dst, const char* format, ...) + // Tell the compiler to do printf format string checking. + PRINTF_ATTRIBUTE(2,3); + +// Append result to a supplied string. +extern void StringAppendF(string* dst, const char* format, ...) + // Tell the compiler to do printf format string checking. + PRINTF_ATTRIBUTE(2,3); + +// Lower-level routine that takes a va_list and appends to a specified string. +// All other routines are just convenience wrappers around it. +extern void StringAppendV(string* dst, const char* format, va_list ap); + +#undef PRINTF_ATTRIBUTE + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_STRINGPRINTF_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc new file mode 100644 index 00000000000..1cf6a7496a7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc @@ -0,0 +1,193 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_NO_SUITESPARSE + +#include "ceres/suitesparse.h" + +#include "cholmod.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/triplet_sparse_matrix.h" +namespace ceres { +namespace internal { + +cholmod_sparse* SuiteSparse::CreateSparseMatrix(TripletSparseMatrix* A) { + cholmod_triplet triplet; + + triplet.nrow = A->num_rows(); + triplet.ncol = A->num_cols(); + triplet.nzmax = A->max_num_nonzeros(); + triplet.nnz = A->num_nonzeros(); + triplet.i = reinterpret_cast(A->mutable_rows()); + triplet.j = reinterpret_cast(A->mutable_cols()); + triplet.x = reinterpret_cast(A->mutable_values()); + triplet.stype = 0; // Matrix is not symmetric. + triplet.itype = CHOLMOD_INT; + triplet.xtype = CHOLMOD_REAL; + triplet.dtype = CHOLMOD_DOUBLE; + + return cholmod_triplet_to_sparse(&triplet, triplet.nnz, &cc_); +} + + +cholmod_sparse* SuiteSparse::CreateSparseMatrixTranspose( + TripletSparseMatrix* A) { + cholmod_triplet triplet; + + triplet.ncol = A->num_rows(); // swap row and columns + triplet.nrow = A->num_cols(); + triplet.nzmax = A->max_num_nonzeros(); + triplet.nnz = A->num_nonzeros(); + + // swap rows and columns + triplet.j = reinterpret_cast(A->mutable_rows()); + triplet.i = reinterpret_cast(A->mutable_cols()); + triplet.x = reinterpret_cast(A->mutable_values()); + triplet.stype = 0; // Matrix is not symmetric. + triplet.itype = CHOLMOD_INT; + triplet.xtype = CHOLMOD_REAL; + triplet.dtype = CHOLMOD_DOUBLE; + + return cholmod_triplet_to_sparse(&triplet, triplet.nnz, &cc_); +} + +cholmod_sparse* SuiteSparse::CreateSparseMatrixTransposeView( + CompressedRowSparseMatrix* A) { + cholmod_sparse* m = new cholmod_sparse_struct; + m->nrow = A->num_cols(); + m->ncol = A->num_rows(); + m->nzmax = A->num_nonzeros(); + + m->p = reinterpret_cast(A->mutable_rows()); + m->i = reinterpret_cast(A->mutable_cols()); + m->x = reinterpret_cast(A->mutable_values()); + + m->stype = 0; // Matrix is not symmetric. + m->itype = CHOLMOD_INT; + m->xtype = CHOLMOD_REAL; + m->dtype = CHOLMOD_DOUBLE; + m->sorted = 1; + m->packed = 1; + + return m; +} + +cholmod_dense* SuiteSparse::CreateDenseVector(const double* x, + int in_size, + int out_size) { + CHECK_LE(in_size, out_size); + cholmod_dense* v = cholmod_zeros(out_size, 1, CHOLMOD_REAL, &cc_); + if (x != NULL) { + memcpy(v->x, x, in_size*sizeof(*x)); + } + return v; +} + +cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A) { + cholmod_factor* factor = cholmod_analyze(A, &cc_); + CHECK_EQ(cc_.status, CHOLMOD_OK) + << "Cholmod symbolic analysis failed " << cc_.status; + CHECK_NOTNULL(factor); + return factor; +} + +bool SuiteSparse::Cholesky(cholmod_sparse* A, cholmod_factor* L) { + CHECK_NOTNULL(A); + CHECK_NOTNULL(L); + + cc_.quick_return_if_not_posdef = 1; + int status = cholmod_factorize(A, L, &cc_); + switch (cc_.status) { + case CHOLMOD_NOT_INSTALLED: + LOG(WARNING) << "Cholmod failure: method not installed."; + return false; + case CHOLMOD_OUT_OF_MEMORY: + LOG(WARNING) << "Cholmod failure: out of memory."; + return false; + case CHOLMOD_TOO_LARGE: + LOG(WARNING) << "Cholmod failure: integer overflow occured."; + return false; + case CHOLMOD_INVALID: + LOG(WARNING) << "Cholmod failure: invalid input."; + return false; + case CHOLMOD_NOT_POSDEF: + // TODO(sameeragarwal): These two warnings require more + // sophisticated handling going forward. For now we will be + // strict and treat them as failures. + LOG(WARNING) << "Cholmod warning: matrix not positive definite."; + return false; + case CHOLMOD_DSMALL: + LOG(WARNING) << "Cholmod warning: D for LDL' or diag(L) or " + << "LL' has tiny absolute value."; + return false; + case CHOLMOD_OK: + if (status != 0) { + return true; + } + LOG(WARNING) << "Cholmod failure: cholmod_factorize returned zero " + << "but cholmod_common::status is CHOLMOD_OK." + << "Please report this to ceres-solver@googlegroups.com."; + return false; + default: + LOG(WARNING) << "Unknown cholmod return code. " + << "Please report this to ceres-solver@googlegroups.com."; + return false; + } + return false; +} + +cholmod_dense* SuiteSparse::Solve(cholmod_factor* L, + cholmod_dense* b) { + if (cc_.status != CHOLMOD_OK) { + LOG(WARNING) << "CHOLMOD status NOT OK"; + return NULL; + } + + return cholmod_solve(CHOLMOD_A, L, b, &cc_); +} + +cholmod_dense* SuiteSparse::SolveCholesky(cholmod_sparse* A, + cholmod_factor* L, + cholmod_dense* b) { + CHECK_NOTNULL(A); + CHECK_NOTNULL(L); + CHECK_NOTNULL(b); + + if (Cholesky(A, L)) { + return Solve(L, b); + } + + return NULL; +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_SUITESPARSE diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h new file mode 100644 index 00000000000..091e67a69a9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h @@ -0,0 +1,159 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// A simple C++ interface to the SuiteSparse and CHOLMOD libraries. + +#ifndef CERES_INTERNAL_SUITESPARSE_H_ +#define CERES_INTERNAL_SUITESPARSE_H_ + +#ifndef CERES_NO_SUITESPARSE + +#include +#include + +#include +#include "cholmod.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +class CompressedRowSparseMatrix; +class TripletSparseMatrix; + +// The raw CHOLMOD and SuiteSparseQR libraries have a slightly +// cumbersome c like calling format. This object abstracts it away and +// provides the user with a simpler interface. The methods here cannot +// be static as a cholmod_common object serves as a global variable +// for all cholmod function calls. +class SuiteSparse { + public: + SuiteSparse() { cholmod_start(&cc_); } + ~SuiteSparse() { cholmod_finish(&cc_); } + + // Functions for building cholmod_sparse objects from sparse + // matrices stored in triplet form. The matrix A is not + // modifed. Called owns the result. + cholmod_sparse* CreateSparseMatrix(TripletSparseMatrix* A); + + // This function works like CreateSparseMatrix, except that the + // return value corresponds to A' rather than A. + cholmod_sparse* CreateSparseMatrixTranspose(TripletSparseMatrix* A); + + // Create a cholmod_sparse wrapper around the contents of A. This is + // a shallow object, which refers to the contents of A and does not + // use the SuiteSparse machinery to allocate memory, this object + // should be disposed off with a delete and not a call to Free as is + // the case for objects returned by CreateSparseMatrixTranspose. + cholmod_sparse* CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A); + + // Given a vector x, build a cholmod_dense vector of size out_size + // with the first in_size entries copied from x. If x is NULL, then + // an all zeros vector is returned. Caller owns the result. + cholmod_dense* CreateDenseVector(const double* x, int in_size, int out_size); + + // The matrix A is scaled using the matrix whose diagonal is the + // vector scale. mode describes how scaling is applied. Possible + // values are CHOLMOD_ROW for row scaling - diag(scale) * A, + // CHOLMOD_COL for column scaling - A * diag(scale) and CHOLMOD_SYM + // for symmetric scaling which scales both the rows and the columns + // - diag(scale) * A * diag(scale). + void Scale(cholmod_dense* scale, int mode, cholmod_sparse* A) { + cholmod_scale(scale, mode, A, &cc_); + } + + // Create and return a matrix m = A * A'. Caller owns the + // result. The matrix A is not modified. + cholmod_sparse* AATranspose(cholmod_sparse* A) { + cholmod_sparse*m = cholmod_aat(A, NULL, A->nrow, 1, &cc_); + m->stype = 1; // Pay attention to the upper triangular part. + return m; + } + + // y = alpha * A * x + beta * y. Only y is modified. + void SparseDenseMultiply(cholmod_sparse* A, double alpha, double beta, + cholmod_dense* x, cholmod_dense* y) { + double alpha_[2] = {alpha, 0}; + double beta_[2] = {beta, 0}; + cholmod_sdmult(A, 0, alpha_, beta_, x, y, &cc_); + } + + // Analyze the sparsity structure of the matrix A compute the + // symbolic factorization of A. A is not modified, only the pattern + // of non-zeros of A is used, the actual numerical values in A are + // of no consequence. Caller owns the result. + cholmod_factor* AnalyzeCholesky(cholmod_sparse* A); + + // Use the symbolic factorization in L, to find the numerical + // factorization for the matrix A or AA^T. Return true if + // successful, false otherwise. L contains the numeric factorization + // on return. + bool Cholesky(cholmod_sparse* A, cholmod_factor* L); + + // Given a Cholesky factorization of a matrix A = LL^T, solve the + // linear system Ax = b, and return the result. If the Solve fails + // NULL is returned. Caller owns the result. + cholmod_dense* Solve(cholmod_factor* L, cholmod_dense* b); + + // Combine the calls to Cholesky and Solve into a single call. If + // the cholesky factorization or the solve fails, return + // NULL. Caller owns the result. + cholmod_dense* SolveCholesky(cholmod_sparse* A, + cholmod_factor* L, + cholmod_dense* b); + + void Free(cholmod_sparse* m) { cholmod_free_sparse(&m, &cc_); } + void Free(cholmod_dense* m) { cholmod_free_dense(&m, &cc_); } + void Free(cholmod_factor* m) { cholmod_free_factor(&m, &cc_); } + + void Print(cholmod_sparse* m, const string& name) { + cholmod_print_sparse(m, const_cast(name.c_str()), &cc_); + } + + void Print(cholmod_dense* m, const string& name) { + cholmod_print_dense(m, const_cast(name.c_str()), &cc_); + } + + void Print(cholmod_triplet* m, const string& name) { + cholmod_print_triplet(m, const_cast(name.c_str()), &cc_); + } + + cholmod_common* mutable_cc() { return &cc_; } + + private: + cholmod_common cc_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_SUITESPARSE + +#endif // CERES_INTERNAL_SUITESPARSE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc new file mode 100644 index 00000000000..7d7c3df9960 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc @@ -0,0 +1,299 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/triplet_sparse_matrix.h" + +#include +#include +#include +#include "ceres/matrix_proto.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +TripletSparseMatrix::TripletSparseMatrix() + : num_rows_(0), + num_cols_(0), + max_num_nonzeros_(0), + num_nonzeros_(0), + rows_(NULL), + cols_(NULL), + values_(NULL) {} + +TripletSparseMatrix::~TripletSparseMatrix() {} + +TripletSparseMatrix::TripletSparseMatrix(int num_rows, + int num_cols, + int max_num_nonzeros) + : num_rows_(num_rows), + num_cols_(num_cols), + max_num_nonzeros_(max_num_nonzeros), + num_nonzeros_(0), + rows_(NULL), + cols_(NULL), + values_(NULL) { + // All the sizes should at least be zero + CHECK_GE(num_rows, 0); + CHECK_GE(num_cols, 0); + CHECK_GE(max_num_nonzeros, 0); + AllocateMemory(); +} + +TripletSparseMatrix::TripletSparseMatrix(const TripletSparseMatrix& orig) + : num_rows_(orig.num_rows_), + num_cols_(orig.num_cols_), + max_num_nonzeros_(orig.max_num_nonzeros_), + num_nonzeros_(orig.num_nonzeros_), + rows_(NULL), + cols_(NULL), + values_(NULL) { + AllocateMemory(); + CopyData(orig); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +TripletSparseMatrix::TripletSparseMatrix(const SparseMatrixProto& outer_proto) { + CHECK(outer_proto.has_triplet_matrix()); + + const TripletSparseMatrixProto& proto = outer_proto.triplet_matrix(); + CHECK(proto.has_num_rows()); + CHECK(proto.has_num_cols()); + CHECK_EQ(proto.rows_size(), proto.cols_size()); + CHECK_EQ(proto.cols_size(), proto.values_size()); + + // Initialize the matrix with the appropriate size and capacity. + max_num_nonzeros_ = 0; + set_num_nonzeros(0); + Reserve(proto.num_nonzeros()); + Resize(proto.num_rows(), proto.num_cols()); + set_num_nonzeros(proto.num_nonzeros()); + + // Copy the entries in. + for (int i = 0; i < proto.num_nonzeros(); ++i) { + rows_[i] = proto.rows(i); + cols_[i] = proto.cols(i); + values_[i] = proto.values(i); + } +} +#endif + +TripletSparseMatrix& TripletSparseMatrix::operator=( + const TripletSparseMatrix& rhs) { + num_rows_ = rhs.num_rows_; + num_cols_ = rhs.num_cols_; + num_nonzeros_ = rhs.num_nonzeros_; + max_num_nonzeros_ = rhs.max_num_nonzeros_; + AllocateMemory(); + CopyData(rhs); + return *this; +} + +bool TripletSparseMatrix::AllTripletsWithinBounds() const { + for (int i = 0; i < num_nonzeros_; ++i) { + if ((rows_[i] < 0) || (rows_[i] >= num_rows_) || + (cols_[i] < 0) || (cols_[i] >= num_cols_)) + return false; + } + return true; +} + +void TripletSparseMatrix::Reserve(int new_max_num_nonzeros) { + CHECK_LE(num_nonzeros_, new_max_num_nonzeros) + << "Reallocation will cause data loss"; + + // Nothing to do if we have enough space already. + if (new_max_num_nonzeros <= max_num_nonzeros_) + return; + + int* new_rows = new int[new_max_num_nonzeros]; + int* new_cols = new int[new_max_num_nonzeros]; + double* new_values = new double[new_max_num_nonzeros]; + + for (int i = 0; i < num_nonzeros_; ++i) { + new_rows[i] = rows_[i]; + new_cols[i] = cols_[i]; + new_values[i] = values_[i]; + } + + rows_.reset(new_rows); + cols_.reset(new_cols); + values_.reset(new_values); + + max_num_nonzeros_ = new_max_num_nonzeros; +} + +void TripletSparseMatrix::SetZero() { + fill(values_.get(), values_.get() + max_num_nonzeros_, 0.0); + num_nonzeros_ = 0; +} + +void TripletSparseMatrix::set_num_nonzeros(int num_nonzeros) { + CHECK_GE(num_nonzeros, 0); + CHECK_LE(num_nonzeros, max_num_nonzeros_); + num_nonzeros_ = num_nonzeros; +}; + +void TripletSparseMatrix::AllocateMemory() { + rows_.reset(new int[max_num_nonzeros_]); + cols_.reset(new int[max_num_nonzeros_]); + values_.reset(new double[max_num_nonzeros_]); +} + +void TripletSparseMatrix::CopyData(const TripletSparseMatrix& orig) { + for (int i = 0; i < num_nonzeros_; ++i) { + rows_[i] = orig.rows_[i]; + cols_[i] = orig.cols_[i]; + values_[i] = orig.values_[i]; + } +} + +void TripletSparseMatrix::RightMultiply(const double* x, double* y) const { + for (int i = 0; i < num_nonzeros_; ++i) { + y[rows_[i]] += values_[i]*x[cols_[i]]; + } +} + +void TripletSparseMatrix::LeftMultiply(const double* x, double* y) const { + for (int i = 0; i < num_nonzeros_; ++i) { + y[cols_[i]] += values_[i]*x[rows_[i]]; + } +} + +void TripletSparseMatrix::SquaredColumnNorm(double* x) const { + CHECK_NOTNULL(x); + VectorRef(x, num_cols_).setZero(); + for (int i = 0; i < num_nonzeros_; ++i) { + x[cols_[i]] += values_[i] * values_[i]; + } +} + +void TripletSparseMatrix::ScaleColumns(const double* scale) { + CHECK_NOTNULL(scale); + for (int i = 0; i < num_nonzeros_; ++i) { + values_[i] = values_[i] * scale[cols_[i]]; + } +} + +void TripletSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { + dense_matrix->resize(num_rows_, num_cols_); + dense_matrix->setZero(); + Matrix& m = *dense_matrix; + for (int i = 0; i < num_nonzeros_; ++i) { + m(rows_[i], cols_[i]) += values_[i]; + } +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void TripletSparseMatrix::ToProto(SparseMatrixProto *proto) const { + proto->Clear(); + + TripletSparseMatrixProto* tsm_proto = proto->mutable_triplet_matrix(); + tsm_proto->set_num_rows(num_rows_); + tsm_proto->set_num_cols(num_cols_); + tsm_proto->set_num_nonzeros(num_nonzeros_); + for (int i = 0; i < num_nonzeros_; ++i) { + tsm_proto->add_rows(rows_[i]); + tsm_proto->add_cols(cols_[i]); + tsm_proto->add_values(values_[i]); + } +} +#endif + +void TripletSparseMatrix::AppendRows(const TripletSparseMatrix& B) { + CHECK_EQ(B.num_cols(), num_cols_); + Reserve(num_nonzeros_ + B.num_nonzeros_); + for (int i = 0; i < B.num_nonzeros_; ++i) { + rows_.get()[num_nonzeros_] = B.rows()[i] + num_rows_; + cols_.get()[num_nonzeros_] = B.cols()[i]; + values_.get()[num_nonzeros_++] = B.values()[i]; + } + num_rows_ = num_rows_ + B.num_rows(); +} + +void TripletSparseMatrix::AppendCols(const TripletSparseMatrix& B) { + CHECK_EQ(B.num_rows(), num_rows_); + Reserve(num_nonzeros_ + B.num_nonzeros_); + for (int i = 0; i < B.num_nonzeros_; ++i, ++num_nonzeros_) { + rows_.get()[num_nonzeros_] = B.rows()[i]; + cols_.get()[num_nonzeros_] = B.cols()[i] + num_cols_; + values_.get()[num_nonzeros_] = B.values()[i]; + } + num_cols_ = num_cols_ + B.num_cols(); +} + + +void TripletSparseMatrix::Resize(int new_num_rows, int new_num_cols) { + if ((new_num_rows >= num_rows_) && (new_num_cols >= num_cols_)) { + num_rows_ = new_num_rows; + num_cols_ = new_num_cols; + return; + } + + num_rows_ = new_num_rows; + num_cols_ = new_num_cols; + + int* r_ptr = rows_.get(); + int* c_ptr = cols_.get(); + double* v_ptr = values_.get(); + + int dropped_terms = 0; + for (int i = 0; i < num_nonzeros_; ++i) { + if ((r_ptr[i] < num_rows_) && (c_ptr[i] < num_cols_)) { + if (dropped_terms) { + r_ptr[i-dropped_terms] = r_ptr[i]; + c_ptr[i-dropped_terms] = c_ptr[i]; + v_ptr[i-dropped_terms] = v_ptr[i]; + } + } else { + ++dropped_terms; + } + } + num_nonzeros_ -= dropped_terms; +} + +TripletSparseMatrix* TripletSparseMatrix::CreateSparseDiagonalMatrix( + const double* values, int num_rows) { + TripletSparseMatrix* m = + new TripletSparseMatrix(num_rows, num_rows, num_rows); + for (int i = 0; i < num_rows; ++i) { + m->mutable_rows()[i] = i; + m->mutable_cols()[i] = i; + m->mutable_values()[i] = values[i]; + } + m->set_num_nonzeros(num_rows); + return m; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h new file mode 100644 index 00000000000..3c90a62fd20 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h @@ -0,0 +1,136 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_TRIPLET_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_TRIPLET_SPARSE_MATRIX_H_ + +#include "ceres/sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; + +// An implementation of the SparseMatrix interface to store and +// manipulate sparse matrices in triplet (i,j,s) form. This object is +// inspired by the design of the cholmod_triplet struct used in the +// SuiteSparse package and is memory layout compatible with it. +class TripletSparseMatrix : public SparseMatrix { + public: + TripletSparseMatrix(); + TripletSparseMatrix(int num_rows, int num_cols, int max_num_nonzeros); + explicit TripletSparseMatrix(const TripletSparseMatrix& orig); +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + explicit TripletSparseMatrix(const SparseMatrixProto& proto); +#endif + + TripletSparseMatrix& operator=(const TripletSparseMatrix& rhs); + + ~TripletSparseMatrix(); + + // Implementation of the SparseMatrix interface. + virtual void SetZero(); + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual void SquaredColumnNorm(double* x) const; + virtual void ScaleColumns(const double* scale); + virtual void ToDenseMatrix(Matrix* dense_matrix) const; +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + virtual void ToProto(SparseMatrixProto *proto) const; +#endif + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_cols_; } + virtual int num_nonzeros() const { return num_nonzeros_; } + virtual const double* values() const { return values_.get(); } + virtual double* mutable_values() { return values_.get(); } + virtual void set_num_nonzeros(int num_nonzeros); + + // Increase max_num_nonzeros and correspondingly increase the size + // of rows_, cols_ and values_. If new_max_num_nonzeros is smaller + // than max_num_nonzeros_, then num_non_zeros should be less than or + // equal to new_max_num_nonzeros, otherwise data loss is possible + // and the method crashes. + void Reserve(int new_max_num_nonzeros); + + // Append the matrix B at the bottom of this matrix. B should have + // the same number of columns as num_cols_. + void AppendRows(const TripletSparseMatrix& B); + + // Append the matrix B at the right of this matrix. B should have + // the same number of rows as num_rows_; + void AppendCols(const TripletSparseMatrix& B); + + // Resize the matrix. Entries which fall outside the new matrix + // bounds are dropped and the num_non_zeros changed accordingly. + void Resize(int new_num_rows, int new_num_cols); + + int max_num_nonzeros() const { return max_num_nonzeros_; } + const int* rows() const { return rows_.get(); } + const int* cols() const { return cols_.get(); } + int* mutable_rows() { return rows_.get(); } + int* mutable_cols() { return cols_.get(); } + + // Returns true if the entries of the matrix obey the row, column, + // and column size bounds and false otherwise. + bool AllTripletsWithinBounds() const; + + bool IsValid() const { return AllTripletsWithinBounds(); } + + // Build a sparse diagonal matrix of size num_rows x num_rows from + // the array values. Entries of the values array are copied into the + // sparse matrix. + static TripletSparseMatrix* CreateSparseDiagonalMatrix(const double* values, + int num_rows); + + private: + void AllocateMemory(); + void CopyData(const TripletSparseMatrix& orig); + + int num_rows_; + int num_cols_; + int max_num_nonzeros_; + int num_nonzeros_; + + // The data is stored as three arrays. For each i, values_[i] is + // stored at the location (rows_[i], cols_[i]). If the there are + // multiple entries with the same (rows_[i], cols_[i]), the values_ + // entries corresponding to them are summed up. + scoped_array rows_; + scoped_array cols_; + scoped_array values_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_TRIPLET_SPARSE_MATRIX_H__ diff --git a/extern/libmv/third_party/ceres/internal/ceres/types.cc b/extern/libmv/third_party/ceres/internal/ceres/types.cc new file mode 100644 index 00000000000..860f8a43f37 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/types.cc @@ -0,0 +1,98 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include +#include "ceres/types.h" + +namespace ceres { + +#define CASESTR(x) case x: return #x + +const char* LinearSolverTypeToString(LinearSolverType solver_type) { + switch (solver_type) { + CASESTR(SPARSE_NORMAL_CHOLESKY); + CASESTR(DENSE_QR); + CASESTR(DENSE_SCHUR); + CASESTR(SPARSE_SCHUR); + CASESTR(ITERATIVE_SCHUR); + CASESTR(CGNR); + default: + return "UNKNOWN"; + } +} + +const char* PreconditionerTypeToString( + PreconditionerType preconditioner_type) { + switch (preconditioner_type) { + CASESTR(IDENTITY); + CASESTR(JACOBI); + CASESTR(SCHUR_JACOBI); + CASESTR(CLUSTER_JACOBI); + CASESTR(CLUSTER_TRIDIAGONAL); + default: + return "UNKNOWN"; + } +} + +const char* OrderingTypeToString(OrderingType ordering_type) { + switch (ordering_type) { + CASESTR(NATURAL); + CASESTR(USER); + CASESTR(SCHUR); + default: + return "UNKNOWN"; + } +} + +const char* SolverTerminationTypeToString( + SolverTerminationType termination_type) { + switch (termination_type) { + CASESTR(NO_CONVERGENCE); + CASESTR(FUNCTION_TOLERANCE); + CASESTR(GRADIENT_TOLERANCE); + CASESTR(PARAMETER_TOLERANCE); + CASESTR(NUMERICAL_FAILURE); + CASESTR(USER_ABORT); + CASESTR(USER_SUCCESS); + CASESTR(DID_NOT_RUN); + default: + return "UNKNOWN"; + } +} + +#undef CASESTR + +bool IsSchurType(LinearSolverType type) { + return ((type == SPARSE_SCHUR) || + (type == DENSE_SCHUR) || + (type == ITERATIVE_SCHUR)); +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc new file mode 100644 index 00000000000..fd41648a7af --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc @@ -0,0 +1,150 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: kushalav@google.com (Avanish Kushal) + +#include +#include +#include +#include +#include +#include + +#include +#include "ceres/block_structure.h" +#include "ceres/collections_port.h" +#include "ceres/graph.h" + +namespace ceres { +namespace internal { + +void ComputeVisibility(const CompressedRowBlockStructure& block_structure, + const int num_eliminate_blocks, + vector< set >* visibility) { + CHECK_NOTNULL(visibility); + + // Clear the visibility vector and resize it to hold a + // vector for each camera. + visibility->resize(0); + visibility->resize(block_structure.cols.size() - num_eliminate_blocks); + + for (int i = 0; i < block_structure.rows.size(); ++i) { + const vector& cells = block_structure.rows[i].cells; + int block_id = cells[0].block_id; + // If the first block is not an e_block, then skip this row block. + if (block_id >= num_eliminate_blocks) { + continue; + } + + for (int j = 1; j < cells.size(); ++j) { + int camera_block_id = cells[j].block_id - num_eliminate_blocks; + DCHECK_GE(camera_block_id, 0); + DCHECK_LT(camera_block_id, visibility->size()); + (*visibility)[camera_block_id].insert(block_id); + } + } +} + +Graph* CreateSchurComplementGraph(const vector >& visibility) { + const time_t start_time = time(NULL); + // Compute the number of e_blocks/point blocks. Since the visibility + // set for each e_block/camera contains the set of e_blocks/points + // visible to it, we find the maximum across all visibility sets. + int num_points = 0; + for (int i = 0; i < visibility.size(); i++) { + if (visibility[i].size() > 0) { + num_points = max(num_points, (*visibility[i].rbegin()) + 1); + } + } + + // Invert the visibility. The input is a camera->point mapping, + // which tells us which points are visible in which + // cameras. However, to compute the sparsity structure of the Schur + // Complement efficiently, its better to have the point->camera + // mapping. + vector > inverse_visibility(num_points); + for (int i = 0; i < visibility.size(); i++) { + const set& visibility_set = visibility[i]; + for (set::const_iterator it = visibility_set.begin(); + it != visibility_set.end(); + ++it) { + inverse_visibility[*it].insert(i); + } + } + + // Map from camera pairs to number of points visible to both cameras + // in the pair. + HashMap, int > camera_pairs; + + // Count the number of points visible to each camera/f_block pair. + for (vector >::const_iterator it = inverse_visibility.begin(); + it != inverse_visibility.end(); + ++it) { + const set& inverse_visibility_set = *it; + for (set::const_iterator camera1 = inverse_visibility_set.begin(); + camera1 != inverse_visibility_set.end(); + ++camera1) { + set::const_iterator camera2 = camera1; + for (++camera2; camera2 != inverse_visibility_set.end(); ++camera2) { + ++(camera_pairs[make_pair(*camera1, *camera2)]); + } + } + } + + Graph* graph = new Graph(); + + // Add vertices and initialize the pairs for self edges so that self + // edges are guaranteed. This is needed for the Canonical views + // algorithm to work correctly. + static const double kSelfEdgeWeight = 1.0; + for (int i = 0; i < visibility.size(); ++i) { + graph->AddVertex(i); + graph->AddEdge(i, i, kSelfEdgeWeight); + } + + // Add an edge for each camera pair. + for (HashMap, int>::const_iterator it = camera_pairs.begin(); + it != camera_pairs.end(); + ++it) { + const int camera1 = it->first.first; + const int camera2 = it->first.second; + CHECK_NE(camera1, camera2); + + const int count = it->second; + // Static cast necessary for Windows. + const double weight = static_cast(count) / + (sqrt(static_cast(visibility[camera1].size() * visibility[camera2].size()))); + graph->AddEdge(camera1, camera2, weight); + } + + VLOG(2) << "Schur complement graph time: " << (time(NULL) - start_time); + return graph; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.h b/extern/libmv/third_party/ceres/internal/ceres/visibility.h new file mode 100644 index 00000000000..692dd87201e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.h @@ -0,0 +1,77 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: kushalav@google.com (Avanish Kushal) +// sameeragarwal@google.com (Sameer Agarwal) +// +// Functions to manipulate visibility information from the block +// structure of sparse matrices. + +#ifndef CERES_INTERNAL_VISIBILITY_H_ +#define CERES_INTERNAL_VISIBILITY_H_ + +#include +#include +#include "ceres/graph.h" + +namespace ceres { +namespace internal { + +class CompressedRowBlockStructure; + +// Given a compressed row block structure, computes the set of +// e_blocks "visible" to each f_block. If an e_block co-occurs with an +// f_block in a residual block, it is visible to the f_block. The +// first num_eliminate_blocks columns blocks are e_blocks and the rest +// f_blocks. +// +// In a structure from motion problem, e_blocks correspond to 3D +// points and f_blocks correspond to cameras. +void ComputeVisibility(const CompressedRowBlockStructure& block_structure, + int num_eliminate_blocks, + vector >* visibility); + +// Given f_block visibility as computed by the ComputeVisibility +// function above, construct and return a graph whose vertices are +// f_blocks and an edge connects two vertices if they have atleast one +// e_block in common. The weight of this edge is normalized dot +// product between the visibility vectors of the two +// vertices/f_blocks. +// +// This graph reflects the sparsity structure of reduced camera +// matrix/Schur complement matrix obtained by eliminating the e_blocks +// from the normal equations. +// +// Caller acquires ownership of the returned Graph pointer +// (heap-allocated). +Graph* CreateSchurComplementGraph(const vector >& visibility); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_VISIBILITY_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc new file mode 100644 index 00000000000..aca77528215 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc @@ -0,0 +1,611 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/visibility_based_preconditioner.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Eigen/Dense" +#include "ceres/block_random_access_sparse_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/canonical_views_clustering.h" +#include "ceres/collections_port.h" +#include "ceres/detect_structure.h" +#include "ceres/graph.h" +#include "ceres/graph_algorithms.h" +#include "ceres/linear_solver.h" +#include "ceres/schur_eliminator.h" +#include "ceres/visibility.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +// TODO(sameeragarwal): Currently these are magic weights for the +// preconditioner construction. Move these higher up into the Options +// struct and provide some guidelines for choosing them. +// +// This will require some more work on the clustering algorithm and +// possibly some more refactoring of the code. +static const double kSizePenaltyWeight = 3.0; +static const double kSimilarityPenaltyWeight = 0.0; + +#ifndef CERES_NO_SUITESPARSE +VisibilityBasedPreconditioner::VisibilityBasedPreconditioner( + const CompressedRowBlockStructure& bs, + const LinearSolver::Options& options) + : options_(options), + num_blocks_(0), + num_clusters_(0), + factor_(NULL) { + CHECK_GT(options_.num_eliminate_blocks, 0); + CHECK(options_.preconditioner_type == SCHUR_JACOBI || + options_.preconditioner_type == CLUSTER_JACOBI || + options_.preconditioner_type == CLUSTER_TRIDIAGONAL) + << "Unknown preconditioner type: " << options_.preconditioner_type; + num_blocks_ = bs.cols.size() - options_.num_eliminate_blocks; + CHECK_GT(num_blocks_, 0) + << "Jacobian should have atleast 1 f_block for " + << "visibility based preconditioning."; + + // Vector of camera block sizes + block_size_.resize(num_blocks_); + for (int i = 0; i < num_blocks_; ++i) { + block_size_[i] = bs.cols[i + options_.num_eliminate_blocks].size; + } + + const time_t start_time = time(NULL); + switch (options_.preconditioner_type) { + case SCHUR_JACOBI: + ComputeSchurJacobiSparsity(bs); + break; + case CLUSTER_JACOBI: + ComputeClusterJacobiSparsity(bs); + break; + case CLUSTER_TRIDIAGONAL: + ComputeClusterTridiagonalSparsity(bs); + break; + default: + LOG(FATAL) << "Unknown preconditioner type"; + } + const time_t structure_time = time(NULL); + InitStorage(bs); + const time_t storage_time = time(NULL); + InitEliminator(bs); + const time_t eliminator_time = time(NULL); + + // Allocate temporary storage for a vector used during + // RightMultiply. + tmp_rhs_ = CHECK_NOTNULL(ss_.CreateDenseVector(NULL, + m_->num_rows(), + m_->num_rows())); + const time_t init_time = time(NULL); + VLOG(2) << "init time: " + << init_time - start_time + << " structure time: " << structure_time - start_time + << " storage time:" << storage_time - structure_time + << " eliminator time: " << eliminator_time - storage_time; +} + +VisibilityBasedPreconditioner::~VisibilityBasedPreconditioner() { + if (factor_ != NULL) { + ss_.Free(factor_); + factor_ = NULL; + } + if (tmp_rhs_ != NULL) { + ss_.Free(tmp_rhs_); + tmp_rhs_ = NULL; + } +} + +// Determine the sparsity structure of the SCHUR_JACOBI +// preconditioner. SCHUR_JACOBI is an extreme case of a visibility +// based preconditioner where each camera block corresponds to a +// cluster and there is no interaction between clusters. +void VisibilityBasedPreconditioner::ComputeSchurJacobiSparsity( + const CompressedRowBlockStructure& bs) { + num_clusters_ = num_blocks_; + cluster_membership_.resize(num_blocks_); + cluster_pairs_.clear(); + + // Each camea block is a member of its own cluster and the only + // cluster pairs are the self edges (i,i). + for (int i = 0; i < num_clusters_; ++i) { + cluster_membership_[i] = i; + cluster_pairs_.insert(make_pair(i, i)); + } +} + +// Determine the sparsity structure of the CLUSTER_JACOBI +// preconditioner. It clusters cameras using their scene +// visibility. The clusters form the diagonal blocks of the +// preconditioner matrix. +void VisibilityBasedPreconditioner::ComputeClusterJacobiSparsity( + const CompressedRowBlockStructure& bs) { + vector > visibility; + ComputeVisibility(bs, options_.num_eliminate_blocks, &visibility); + CHECK_EQ(num_blocks_, visibility.size()); + ClusterCameras(visibility); + cluster_pairs_.clear(); + for (int i = 0; i < num_clusters_; ++i) { + cluster_pairs_.insert(make_pair(i, i)); + } +} + +// Determine the sparsity structure of the CLUSTER_TRIDIAGONAL +// preconditioner. It clusters cameras using using the scene +// visibility and then finds the strongly interacting pairs of +// clusters by constructing another graph with the clusters as +// vertices and approximating it with a degree-2 maximum spanning +// forest. The set of edges in this forest are the cluster pairs. +void VisibilityBasedPreconditioner::ComputeClusterTridiagonalSparsity( + const CompressedRowBlockStructure& bs) { + vector > visibility; + ComputeVisibility(bs, options_.num_eliminate_blocks, &visibility); + CHECK_EQ(num_blocks_, visibility.size()); + ClusterCameras(visibility); + + // Construct a weighted graph on the set of clusters, where the + // edges are the number of 3D points/e_blocks visible in both the + // clusters at the ends of the edge. Return an approximate degree-2 + // maximum spanning forest of this graph. + vector > cluster_visibility; + ComputeClusterVisibility(visibility, &cluster_visibility); + scoped_ptr > cluster_graph( + CHECK_NOTNULL(CreateClusterGraph(cluster_visibility))); + scoped_ptr > forest( + CHECK_NOTNULL(Degree2MaximumSpanningForest(*cluster_graph))); + ForestToClusterPairs(*forest, &cluster_pairs_); +} + +// Allocate storage for the preconditioner matrix. +void VisibilityBasedPreconditioner::InitStorage( + const CompressedRowBlockStructure& bs) { + ComputeBlockPairsInPreconditioner(bs); + m_.reset(new BlockRandomAccessSparseMatrix(block_size_, block_pairs_)); +} + +// Call the canonical views algorithm and cluster the cameras based on +// their visibility sets. The visibility set of a camera is the set of +// e_blocks/3D points in the scene that are seen by it. +// +// The cluster_membership_ vector is updated to indicate cluster +// memberships for each camera block. +void VisibilityBasedPreconditioner::ClusterCameras( + const vector >& visibility) { + scoped_ptr > schur_complement_graph( + CHECK_NOTNULL(CreateSchurComplementGraph(visibility))); + + CanonicalViewsClusteringOptions options; + options.size_penalty_weight = kSizePenaltyWeight; + options.similarity_penalty_weight = kSimilarityPenaltyWeight; + + vector centers; + HashMap membership; + ComputeCanonicalViewsClustering(*schur_complement_graph, + options, + ¢ers, + &membership); + num_clusters_ = centers.size(); + CHECK_GT(num_clusters_, 0); + VLOG(2) << "num_clusters: " << num_clusters_; + FlattenMembershipMap(membership, &cluster_membership_); +} + +// Compute the block sparsity structure of the Schur complement +// matrix. For each pair of cameras contributing a non-zero cell to +// the schur complement, determine if that cell is present in the +// preconditioner or not. +// +// A pair of cameras contribute a cell to the preconditioner if they +// are part of the same cluster or if the the two clusters that they +// belong have an edge connecting them in the degree-2 maximum +// spanning forest. +// +// For example, a camera pair (i,j) where i belonges to cluster1 and +// j belongs to cluster2 (assume that cluster1 < cluster2). +// +// The cell corresponding to (i,j) is present in the preconditioner +// if cluster1 == cluster2 or the pair (cluster1, cluster2) were +// connected by an edge in the degree-2 maximum spanning forest. +// +// Since we have already expanded the forest into a set of camera +// pairs/edges, including self edges, the check can be reduced to +// checking membership of (cluster1, cluster2) in cluster_pairs_. +void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner( + const CompressedRowBlockStructure& bs) { + block_pairs_.clear(); + for (int i = 0; i < num_blocks_; ++i) { + block_pairs_.insert(make_pair(i, i)); + } + + int r = 0; + set > skipped_pairs; + const int num_row_blocks = bs.rows.size(); + const int num_eliminate_blocks = options_.num_eliminate_blocks; + + // Iterate over each row of the matrix. The block structure of the + // matrix is assumed to be sorted in order of the e_blocks/point + // blocks. Thus all row blocks containing an e_block/point occur + // contiguously. Further, if present, an e_block is always the first + // parameter block in each row block. These structural assumptions + // are common to all Schur complement based solvers in Ceres. + // + // For each e_block/point block we identify the set of cameras + // seeing it. The cross product of this set with itself is the set + // of non-zero cells contibuted by this e_block. + // + // The time complexity of this is O(nm^2) where, n is the number of + // 3d points and m is the maximum number of cameras seeing any + // point, which for most scenes is a fairly small number. + while (r < num_row_blocks) { + int e_block_id = bs.rows[r].cells.front().block_id; + if (e_block_id >= num_eliminate_blocks) { + // Skip the rows whose first block is an f_block. + break; + } + + set f_blocks; + for (; r < num_row_blocks; ++r) { + const CompressedRow& row = bs.rows[r]; + if (row.cells.front().block_id != e_block_id) { + break; + } + + // Iterate over the blocks in the row, ignoring the first block + // since it is the one to be eliminated and adding the rest to + // the list of f_blocks associated with this e_block. + for (int c = 1; c < row.cells.size(); ++c) { + const Cell& cell = row.cells[c]; + const int f_block_id = cell.block_id - num_eliminate_blocks; + CHECK_GE(f_block_id, 0); + f_blocks.insert(f_block_id); + } + } + + for (set::const_iterator block1 = f_blocks.begin(); + block1 != f_blocks.end(); + ++block1) { + set::const_iterator block2 = block1; + ++block2; + for (; block2 != f_blocks.end(); ++block2) { + if (IsBlockPairInPreconditioner(*block1, *block2)) { + block_pairs_.insert(make_pair(*block1, *block2)); + } else { + skipped_pairs.insert(make_pair(*block1, *block2)); + } + } + } + } + + // The remaining rows which do not contain any e_blocks. + for (; r < num_row_blocks; ++r) { + const CompressedRow& row = bs.rows[r]; + CHECK_GE(row.cells.front().block_id, num_eliminate_blocks); + for (int i = 0; i < row.cells.size(); ++i) { + const int block1 = row.cells[i].block_id - num_eliminate_blocks; + for (int j = 0; j < row.cells.size(); ++j) { + const int block2 = row.cells[j].block_id - num_eliminate_blocks; + if (block1 <= block2) { + if (IsBlockPairInPreconditioner(block1, block2)) { + block_pairs_.insert(make_pair(block1, block2)); + } else { + skipped_pairs.insert(make_pair(block1, block2)); + } + } + } + } + } + + VLOG(1) << "Block pair stats: " + << block_pairs_.size() << " included " + << skipped_pairs.size() << " excluded"; +} + +// Initialize the SchurEliminator. +void VisibilityBasedPreconditioner::InitEliminator( + const CompressedRowBlockStructure& bs) { + LinearSolver::Options eliminator_options; + eliminator_options.num_eliminate_blocks = options_.num_eliminate_blocks; + eliminator_options.num_threads = options_.num_threads; + eliminator_options.constant_sparsity = true; + + DetectStructure(bs, options_.num_eliminate_blocks, + &eliminator_options.row_block_size, + &eliminator_options.e_block_size, + &eliminator_options.f_block_size); + + eliminator_.reset(SchurEliminatorBase::Create(eliminator_options)); + eliminator_->Init(options_.num_eliminate_blocks, &bs); +} + +// Compute the values of the preconditioner matrix and factorize it. +bool VisibilityBasedPreconditioner::Compute(const BlockSparseMatrixBase& A, + const double* D) { + const time_t start_time = time(NULL); + const int num_rows = m_->num_rows(); + CHECK_GT(num_rows, 0); + + // We need a dummy rhs vector and a dummy b vector since the Schur + // eliminator combines the computation of the reduced camera matrix + // with the computation of the right hand side of that linear + // system. + // + // TODO(sameeragarwal): Perhaps its worth refactoring the + // SchurEliminator::Eliminate function to allow NULL for the rhs. As + // of now it does not seem to be worth the effort. + Vector rhs = Vector::Zero(m_->num_rows()); + Vector b = Vector::Zero(A.num_rows()); + + // Compute a subset of the entries of the Schur complement. + eliminator_->Eliminate(&A, b.data(), D, m_.get(), rhs.data()); + + // Try factorizing the matrix. For SCHUR_JACOBI and CLUSTER_JACOBI, + // this should always succeed modulo some numerical/conditioning + // problems. For CLUSTER_TRIDIAGONAL, in general the preconditioner + // matrix as constructed is not positive definite. However, we will + // go ahead and try factorizing it. If it works, great, otherwise we + // scale all the cells in the preconditioner corresponding to the + // edges in the degree-2 forest and that guarantees positive + // definiteness. The proof of this fact can be found in Lemma 1 in + // "Visibility Based Preconditioning for Bundle Adjustment". + // + // Doing the factorization like this saves us matrix mass when + // scaling is not needed, which is quite often in our experience. + bool status = Factorize(); + + // The scaling only affects the tri-diagonal case, since + // ScaleOffDiagonalBlocks only pays attenion to the cells that + // belong to the edges of the degree-2 forest. In the SCHUR_JACOBI + // and the CLUSTER_JACOBI cases, the preconditioner is guaranteed to + // be positive semidefinite. + if (!status && options_.preconditioner_type == CLUSTER_TRIDIAGONAL) { + VLOG(1) << "Unscaled factorization failed. Retrying with off-diagonal " + << "scaling"; + ScaleOffDiagonalCells(); + status = Factorize(); + } + + VLOG(2) << "Compute time: " << time(NULL) - start_time; + return status; +} + +// Consider the preconditioner matrix as meta-block matrix, whose +// blocks correspond to the clusters. Then cluster pairs corresponding +// to edges in the degree-2 forest are off diagonal entries of this +// matrix. Scaling these off-diagonal entries by 1/2 forces this +// matrix to be positive definite. +void VisibilityBasedPreconditioner::ScaleOffDiagonalCells() { + for (set< pair >::const_iterator it = block_pairs_.begin(); + it != block_pairs_.end(); + ++it) { + const int block1 = it->first; + const int block2 = it->second; + if (!IsBlockPairOffDiagonal(block1, block2)) { + continue; + } + + int r, c, row_stride, col_stride; + CellInfo* cell_info = m_->GetCell(block1, block2, + &r, &c, + &row_stride, &col_stride); + CHECK(cell_info != NULL) + << "Cell missing for block pair (" << block1 << "," << block2 << ")" + << " cluster pair (" << cluster_membership_[block1] + << " " << cluster_membership_[block2] << ")"; + + // Ah the magic of tri-diagonal matrices and diagonal + // dominance. See Lemma 1 in "Visibility Based Preconditioning + // For Bundle Adjustment". + MatrixRef m(cell_info->values, row_stride, col_stride); + m.block(r, c, block_size_[block1], block_size_[block2]) *= 0.5; + } +} + +// Compute the sparse Cholesky factorization of the preconditioner +// matrix. +bool VisibilityBasedPreconditioner::Factorize() { + // Extract the TripletSparseMatrix that is used for actually storing + // S and convert it into a cholmod_sparse object. + cholmod_sparse* lhs = ss_.CreateSparseMatrix( + down_cast( + m_.get())->mutable_matrix()); + + // The matrix is symmetric, and the upper triangular part of the + // matrix contains the values. + lhs->stype = 1; + + // Symbolic factorization is computed if we don't already have one + // handy. + if (factor_ == NULL) { + factor_ = ss_.AnalyzeCholesky(lhs); + } + + bool status = ss_.Cholesky(lhs, factor_); + ss_.Free(lhs); + return status; +} + +void VisibilityBasedPreconditioner::RightMultiply(const double* x, + double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + SuiteSparse* ss = const_cast(&ss_); + + const int num_rows = m_->num_rows(); + memcpy(CHECK_NOTNULL(tmp_rhs_)->x, x, m_->num_rows() * sizeof(*x)); + cholmod_dense* solution = CHECK_NOTNULL(ss->Solve(factor_, tmp_rhs_)); + memcpy(y, solution->x, sizeof(*y) * num_rows); + ss->Free(solution); +} + +int VisibilityBasedPreconditioner::num_rows() const { + return m_->num_rows(); +} + +// Classify camera/f_block pairs as in and out of the preconditioner, +// based on whether the cluster pair that they belong to is in the +// preconditioner or not. +bool VisibilityBasedPreconditioner::IsBlockPairInPreconditioner( + const int block1, + const int block2) const { + int cluster1 = cluster_membership_[block1]; + int cluster2 = cluster_membership_[block2]; + if (cluster1 > cluster2) { + std::swap(cluster1, cluster2); + } + return (cluster_pairs_.count(make_pair(cluster1, cluster2)) > 0); +} + +bool VisibilityBasedPreconditioner::IsBlockPairOffDiagonal( + const int block1, + const int block2) const { + return (cluster_membership_[block1] != cluster_membership_[block2]); +} + +// Convert a graph into a list of edges that includes self edges for +// each vertex. +void VisibilityBasedPreconditioner::ForestToClusterPairs( + const Graph& forest, + HashSet >* cluster_pairs) const { + CHECK_NOTNULL(cluster_pairs)->clear(); + const HashSet& vertices = forest.vertices(); + CHECK_EQ(vertices.size(), num_clusters_); + + // Add all the cluster pairs corresponding to the edges in the + // forest. + for (HashSet::const_iterator it1 = vertices.begin(); + it1 != vertices.end(); + ++it1) { + const int cluster1 = *it1; + cluster_pairs->insert(make_pair(cluster1, cluster1)); + const HashSet& neighbors = forest.Neighbors(cluster1); + for (HashSet::const_iterator it2 = neighbors.begin(); + it2 != neighbors.end(); + ++it2) { + const int cluster2 = *it2; + if (cluster1 < cluster2) { + cluster_pairs->insert(make_pair(cluster1, cluster2)); + } + } + } +} + +// The visibilty set of a cluster is the union of the visibilty sets +// of all its cameras. In other words, the set of points visible to +// any camera in the cluster. +void VisibilityBasedPreconditioner::ComputeClusterVisibility( + const vector >& visibility, + vector >* cluster_visibility) const { + CHECK_NOTNULL(cluster_visibility)->resize(0); + cluster_visibility->resize(num_clusters_); + for (int i = 0; i < num_blocks_; ++i) { + const int cluster_id = cluster_membership_[i]; + (*cluster_visibility)[cluster_id].insert(visibility[i].begin(), + visibility[i].end()); + } +} + +// Construct a graph whose vertices are the clusters, and the edge +// weights are the number of 3D points visible to cameras in both the +// vertices. +Graph* VisibilityBasedPreconditioner::CreateClusterGraph( + const vector >& cluster_visibility) const { + Graph* cluster_graph = new Graph; + + for (int i = 0; i < num_clusters_; ++i) { + cluster_graph->AddVertex(i); + } + + for (int i = 0; i < num_clusters_; ++i) { + const set& cluster_i = cluster_visibility[i]; + for (int j = i+1; j < num_clusters_; ++j) { + vector intersection; + const set& cluster_j = cluster_visibility[j]; + set_intersection(cluster_i.begin(), cluster_i.end(), + cluster_j.begin(), cluster_j.end(), + back_inserter(intersection)); + + if (intersection.size() > 0) { + // Clusters interact strongly when they share a large number + // of 3D points. The degree-2 maximum spanning forest + // alorithm, iterates on the edges in decreasing order of + // their weight, which is the number of points shared by the + // two cameras that it connects. + cluster_graph->AddEdge(i, j, intersection.size()); + } + } + } + return cluster_graph; +} + +// Canonical views clustering returns a HashMap from vertices to +// cluster ids. Convert this into a flat array for quick lookup. It is +// possible that some of the vertices may not be associated with any +// cluster. In that case, randomly assign them to one of the clusters. +void VisibilityBasedPreconditioner::FlattenMembershipMap( + const HashMap& membership_map, + vector* membership_vector) const { + CHECK_NOTNULL(membership_vector)->resize(0); + membership_vector->resize(num_blocks_, -1); + // Iterate over the cluster membership map and update the + // cluster_membership_ vector assigning arbitrary cluster ids to + // the few cameras that have not been clustered. + for (HashMap::const_iterator it = membership_map.begin(); + it != membership_map.end(); + ++it) { + const int camera_id = it->first; + int cluster_id = it->second; + + // If the view was not clustered, randomly assign it to one of the + // clusters. This preserves the mathematical correctness of the + // preconditioner. If there are too many views which are not + // clustered, it may lead to some quality degradation though. + // + // TODO(sameeragarwal): Check if a large number of views have not + // been clustered and deal with it? + if (cluster_id == -1) { + cluster_id = camera_id % num_clusters_; + } + + membership_vector->at(camera_id) = cluster_id; + } +} + +#endif // CERES_NO_SUITESPARSE + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h new file mode 100644 index 00000000000..fa095ca1dd8 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h @@ -0,0 +1,273 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Preconditioners for linear systems that arise in Structure from +// Motion problems. VisibilityBasedPreconditioner implements three +// preconditioners: +// +// SCHUR_JACOBI +// CLUSTER_JACOBI +// CLUSTER_TRIDIAGONAL +// +// Detailed descriptions of these preconditions beyond what is +// documented here can be found in +// +// Bundle Adjustment in the Large +// S. Agarwal, N. Snavely, S. Seitz & R. Szeliski, ECCV 2010 +// http://www.cs.washington.edu/homes/sagarwal/bal.pdf +// +// Visibility Based Preconditioning for Bundle Adjustment +// A. Kushal & S. Agarwal, submitted to CVPR 2012 +// http://www.cs.washington.edu/homes/sagarwal/vbp.pdf +// +// The three preconditioners share enough code that its most efficient +// to implement them as part of the same code base. + +#ifndef CERES_INTERNAL_VISIBILITY_BASED_PRECONDITIONER_H_ +#define CERES_INTERNAL_VISIBILITY_BASED_PRECONDITIONER_H_ + +#include +#include +#include +#include "ceres/collections_port.h" +#include "ceres/graph.h" +#include "ceres/linear_solver.h" +#include "ceres/linear_operator.h" +#include "ceres/suitesparse.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +class BlockRandomAccessSparseMatrix; +class BlockSparseMatrixBase; +class CompressedRowBlockStructure; +class SchurEliminatorBase; + +// This class implements three preconditioners for Structure from +// Motion/Bundle Adjustment problems. The name +// VisibilityBasedPreconditioner comes from the fact that the sparsity +// structure of the preconditioner matrix is determined by analyzing +// the visibility structure of the scene, i.e. which cameras see which +// points. +// +// Strictly speaking, SCHUR_JACOBI is not a visibility based +// preconditioner but it is an extreme case of CLUSTER_JACOBI, where +// every cluster contains exactly one camera block. Treating it as a +// special case of CLUSTER_JACOBI makes it easy to implement as part +// of the same code base with no significant loss of performance. +// +// In the following, we will only discuss CLUSTER_JACOBI and +// CLUSTER_TRIDIAGONAL. +// +// The key idea of visibility based preconditioning is to identify +// cameras that we expect have strong interactions, and then using the +// entries in the Schur complement matrix corresponding to these +// camera pairs as an approximation to the full Schur complement. +// +// CLUSTER_JACOBI identifies these camera pairs by clustering cameras, +// and considering all non-zero camera pairs within each cluster. The +// clustering in the current implementation is done using the +// Canonical Views algorithm of Simon et al. (see +// canonical_views_clustering.h). For the purposes of clustering, the +// similarity or the degree of interaction between a pair of cameras +// is measured by counting the number of points visible in both the +// cameras. Thus the name VisibilityBasedPreconditioner. Further, if we +// were to permute the parameter blocks such that all the cameras in +// the same cluster occur contiguously, the preconditioner matrix will +// be a block diagonal matrix with blocks corresponding to the +// clusters. Thus in analogy with the Jacobi preconditioner we refer +// to this as the CLUSTER_JACOBI preconditioner. +// +// CLUSTER_TRIDIAGONAL adds more mass to the CLUSTER_JACOBI +// preconditioner by considering the interaction between clusters and +// identifying strong interactions between cluster pairs. This is done +// by constructing a weighted graph on the clusters, with the weight +// on the edges connecting two clusters proportional to the number of +// 3D points visible to cameras in both the clusters. A degree-2 +// maximum spanning forest is identified in this graph and the camera +// pairs contained in the edges of this forest are added to the +// preconditioner. The detailed reasoning for this construction is +// explained in the paper mentioned above. +// +// Degree-2 spanning trees and forests have the property that they +// correspond to tri-diagonal matrices. Thus there exist a permutation +// of the camera blocks under which the CLUSTER_TRIDIAGONAL +// preconditioner matrix is a block tridiagonal matrix, and thus the +// name for the preconditioner. +// +// Thread Safety: This class is NOT thread safe. +// +// Example usage: +// +// LinearSolver::Options options; +// options.preconditioner_type = CLUSTER_JACOBI; +// options.num_eliminate_blocks = num_points; +// VisibilityBasedPreconditioner preconditioner( +// *A.block_structure(), options); +// preconditioner.Compute(A, NULL); +// preconditioner.RightMultiply(x, y); +// + +#ifndef CERES_NO_SUITESPARSE +class VisibilityBasedPreconditioner : public LinearOperator { + public: + // Initialize the symbolic structure of the preconditioner. bs is + // the block structure of the linear system to be solved. It is used + // to determine the sparsity structure of the preconditioner matrix. + // + // It has the same structural requirement as other Schur complement + // based solvers. Please see schur_eliminator.h for more details. + // + // LinearSolver::Options::num_eliminate_blocks should be set to the + // number of e_blocks in the block structure. + // + // TODO(sameeragarwal): The use of LinearSolver::Options should + // ultimately be replaced with Preconditioner::Options and some sort + // of preconditioner factory along the lines of + // LinearSolver::CreateLinearSolver. I will wait to do this till I + // create a general purpose block Jacobi preconditioner for general + // sparse problems along with a CGLS solver. + VisibilityBasedPreconditioner(const CompressedRowBlockStructure& bs, + const LinearSolver::Options& options); + virtual ~VisibilityBasedPreconditioner(); + + // Compute the numerical value of the preconditioner for the linear + // system: + // + // | A | x = |b| + // |diag(D)| |0| + // + // for some vector b. It is important that the matrix A have the + // same block structure as the one used to construct this object. + // + // D can be NULL, in which case its interpreted as a diagonal matrix + // of size zero. + bool Compute(const BlockSparseMatrixBase& A, + const double* D); + + // LinearOperator interface. Since the operator is symmetric, + // LeftMultiply and num_cols are just calls to RightMultiply and + // num_rows respectively. Compute() must be called before + // RightMultiply can be called. + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const { + RightMultiply(x, y); + } + virtual int num_rows() const; + virtual int num_cols() const { return num_rows(); } + + friend class VisibilityBasedPreconditionerTest; + private: + void ComputeSchurJacobiSparsity(const CompressedRowBlockStructure& bs); + void ComputeClusterJacobiSparsity(const CompressedRowBlockStructure& bs); + void ComputeClusterTridiagonalSparsity(const CompressedRowBlockStructure& bs); + void InitStorage(const CompressedRowBlockStructure& bs); + void InitEliminator(const CompressedRowBlockStructure& bs); + bool Factorize(); + void ScaleOffDiagonalCells(); + + void ClusterCameras(const vector< set >& visibility); + void FlattenMembershipMap(const HashMap& membership_map, + vector* membership_vector) const; + void ComputeClusterVisibility(const vector >& visibility, + vector >* cluster_visibility) const; + Graph* CreateClusterGraph(const vector >& visibility) const; + void ForestToClusterPairs(const Graph& forest, + HashSet >* cluster_pairs) const; + void ComputeBlockPairsInPreconditioner(const CompressedRowBlockStructure& bs); + bool IsBlockPairInPreconditioner(int block1, int block2) const; + bool IsBlockPairOffDiagonal(int block1, int block2) const; + + LinearSolver::Options options_; + + // Number of parameter blocks in the schur complement. + int num_blocks_; + int num_clusters_; + + // Sizes of the blocks in the schur complement. + vector block_size_; + + // Mapping from cameras to clusters. + vector cluster_membership_; + + // Non-zero camera pairs from the schur complement matrix that are + // present in the preconditioner, sorted by row (first element of + // each pair), then column (second). + set > block_pairs_; + + // Set of cluster pairs (including self pairs (i,i)) in the + // preconditioner. + HashSet > cluster_pairs_; + scoped_ptr eliminator_; + + // Preconditioner matrix. + scoped_ptr m_; + + // RightMultiply is a const method for LinearOperators. It is + // implemented using CHOLMOD's sparse triangular matrix solve + // function. This however requires non-const access to the + // SuiteSparse context object, even though it does not result in any + // of the state of the preconditioner being modified. + SuiteSparse ss_; + + // Symbolic and numeric factorization of the preconditioner. + cholmod_factor* factor_; + + // Temporary vector used by RightMultiply. + cholmod_dense* tmp_rhs_; + DISALLOW_COPY_AND_ASSIGN(VisibilityBasedPreconditioner); +}; +#else // SuiteSparse +// If SuiteSparse is not compiled in, the preconditioner is not +// available. +class VisibilityBasedPreconditioner : public LinearOperator { + public: + VisibilityBasedPreconditioner(const CompressedRowBlockStructure& bs, + const LinearSolver::Options& options) { + LOG(FATAL) << "Visibility based preconditioning is not available. Please " + "build Ceres with SuiteSparse."; + } + virtual ~VisibilityBasedPreconditioner() {} + virtual void RightMultiply(const double* x, double* y) const {} + virtual void LeftMultiply(const double* x, double* y) const {} + virtual int num_rows() const { return -1; } + virtual int num_cols() const { return -1; } + bool Compute(const BlockSparseMatrixBase& A, const double* D) { + return false; + } +}; +#endif // CERES_NO_SUITESPARSE + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_VISIBILITY_BASED_PRECONDITIONER_H_ diff --git a/extern/libmv/third_party/ceres/mkfiles.sh b/extern/libmv/third_party/ceres/mkfiles.sh new file mode 100755 index 00000000000..d335829aa2c --- /dev/null +++ b/extern/libmv/third_party/ceres/mkfiles.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +find ./include/ -type f | sed -r 's/^\.\///' | sort > files.txt +find ./internal/ -type f | sed -r 's/^\.\///' | sort >> files.txt diff --git a/extern/libmv/third_party/ceres/patches/series b/extern/libmv/third_party/ceres/patches/series new file mode 100644 index 00000000000..dbe955ae61e --- /dev/null +++ b/extern/libmv/third_party/ceres/patches/series @@ -0,0 +1 @@ +msvc_isfinite.patch diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 70354c0a2ec..dcd4d78d19a 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -171,6 +171,7 @@ endif() if(WITH_LIBMV) list(APPEND BLENDER_SORTED_LIBS extern_libmv) + list(APPEND BLENDER_SORTED_LIBS extern_ceres) endif() list(APPEND BLENDER_SORTED_LIBS extern_colamd) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 5f0386dc28b..5524b50cdf7 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -909,6 +909,7 @@ endif() if(WITH_LIBMV) list(APPEND BLENDER_SORTED_LIBS extern_libmv) + list(APPEND BLENDER_SORTED_LIBS extern_ceres) endif() if(WITH_MOD_CLOTH_ELTOPO) From 7ca990f2a9053175fab1d38250d6c180b024ffd0 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 10 May 2012 10:17:59 +0000 Subject: [PATCH 028/183] Tomato: re-integrate ceres library with updates needed for tracking improvement Also commit missed patch. --- extern/libmv/third_party/ceres/CMakeLists.txt | 10 +- extern/libmv/third_party/ceres/ChangeLog | 97 ++++++++++ .../include/ceres/autodiff_cost_function.h | 67 +++++-- .../ceres/include/ceres/internal/autodiff.h | 52 +++--- .../ceres/include/ceres/sized_cost_function.h | 14 +- .../third_party/ceres/include/ceres/solver.h | 11 +- .../third_party/ceres/include/ceres/types.h | 34 ++++ .../internal/ceres/block_sparse_matrix.cc | 23 +++ .../internal/ceres/block_sparse_matrix.h | 2 + .../ceres/compressed_row_sparse_matrix.cc | 9 + .../ceres/compressed_row_sparse_matrix.h | 2 +- .../internal/ceres/dense_sparse_matrix.cc | 13 ++ .../internal/ceres/dense_sparse_matrix.h | 1 + .../internal/ceres/levenberg_marquardt.cc | 116 ++++-------- .../ceres/linear_least_squares_problems.cc | 170 ++++++++++++++++++ .../ceres/linear_least_squares_problems.h | 12 +- .../ceres/internal/ceres/minimizer.h | 6 +- .../ceres/internal/ceres/sparse_matrix.h | 8 +- .../internal/ceres/triplet_sparse_matrix.cc | 7 + .../internal/ceres/triplet_sparse_matrix.h | 1 + .../ceres/patches/msvc_isfinite.patch | 15 ++ 21 files changed, 527 insertions(+), 143 deletions(-) create mode 100644 extern/libmv/third_party/ceres/patches/msvc_isfinite.patch diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt index 19158dcfebb..5207bddec12 100644 --- a/extern/libmv/third_party/ceres/CMakeLists.txt +++ b/extern/libmv/third_party/ceres/CMakeLists.txt @@ -208,11 +208,11 @@ else() endif() add_definitions( - -DCERES_HAVE_PTHREAD - -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" - -D"CERES_HASH_NAMESPACE_END=}}" - -DCERES_NO_SUITESPARSE - -DCERES_DONT_HAVE_PROTOCOL_BUFFERS + -DCERES_HAVE_PTHREAD + -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" + -D"CERES_HASH_NAMESPACE_END=}}" + -DCERES_NO_SUITESPARSE + -DCERES_DONT_HAVE_PROTOCOL_BUFFERS ) blender_add_lib(extern_ceres "${SRC}" "${INC}" "${INC_SYS}") diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog index c652a73c0c1..6e919658f13 100644 --- a/extern/libmv/third_party/ceres/ChangeLog +++ b/extern/libmv/third_party/ceres/ChangeLog @@ -1,3 +1,100 @@ +commit ca72152362ae1f4b9928c012e74b4d49d094a4ca +Merge: d297f8d 0a04199 +Author: Keir Mierle +Date: Wed May 9 13:10:59 2012 -0700 + + Merge branch 'master' into windows + +commit 0a04199ef279cc9ea97f665fed8e7fae717813c3 +Merge: fdeb577 f2571f1 +Author: Keir Mierle +Date: Wed May 9 12:54:56 2012 -0700 + + Merge branch 'master' of https://code.google.com/p/ceres-solver + +commit fdeb5772cc5eeebca4d776d220d80cc91b6d0f74 +Author: Keir Mierle +Date: Wed May 9 07:38:07 2012 -0700 + + Support varying numbers of residuals in autodiff. + + This commit modifies the only function in autodiff that takes a + templated number of outputs (i.e. residuals) and makes that + template parameter a normal parameter. With that change, it + is a trivial matter to support a dynamic number of residuals. + + The API for dynamic residuals is to pass a fake number of + residuals as the second template argument to + AutoDiffCostFunction, and to pass the real number of + parameters as a second constructor argument. + +commit da3e0563cc12e08e7b3e0fbf11d9cc8cfe9658aa +Author: Sameer Agarwal +Date: Wed May 9 11:57:47 2012 -0700 + + Typo corrections in the documentation from Bing + +commit aa9526d8e8fb34c23d63e3af5bf9239b0c4ea603 +Author: Sameer Agarwal +Date: Tue May 8 21:22:09 2012 -0700 + + Share search paths across various library searches. + Fix typos in glog search. + Split the error messages for include and lib. + Enable building of tests by default. + Made building on homebrew installations a bit better. + Remove temporary variables for glog and gflags. + +commit f2571f186850ed3dd316236ac4be488979df7d30 +Author: Sameer Agarwal +Date: Wed May 9 11:57:47 2012 -0700 + + Typo corrections in the documentation from Bing + +commit 8f7f11ff7d07737435428a2620c52419cf99f98e +Merge: e6c17c4 eaccbb3 +Author: Sameer Agarwal +Date: Wed May 9 11:34:15 2012 -0700 + + Merge branch 'master' of https://code.google.com/p/ceres-solver + +commit e6c17c4c9d9307218f6f739cea39bc2d87733d4d +Author: Sameer Agarwal +Date: Tue May 8 21:22:09 2012 -0700 + + Share search paths across various library searches. + Fix typos in glog search. + Split the error messages for include and lib. + Enable building of tests by default. + Made building on homebrew installations a bit better. + Remove temporary variables for glog and gflags. + +commit eaccbb345614c0d24c5e21fa931f470cfda874df +Author: Keir Mierle +Date: Wed May 9 05:31:29 2012 -0700 + + Remove unused template parameter from VariadicEvaluate. + +commit 82f4b88c34b0b2cf85064e5fc20e374e978b2e3b +Author: Sameer Agarwal +Date: Sun May 6 21:05:28 2012 -0700 + + Extend support writing linear least squares problems to disk. + + 1. Make the mechanism for writing problems to disk, generic and + controllable using an enum DumpType visible in the API. + + 2. Instead of single file containing protocol buffers, now matrices can + be written in a matlab/octave friendly format. This is now the default. + + 3. The support for writing problems to disk is moved into + linear_least_squares_problem.cc/h + + 4. SparseMatrix now has a ToTextFile virtual method which is + implemented by each of its subclasses to write a (i,j,s) triplets. + + 5. Minor changes to simple_bundle_adjuster to enable logging at startup. + commit d297f8d3d3f5025c24752f0f4c1ec2469a769f99 Merge: 7e74d81 f8bd7fa Author: Keir Mierle diff --git a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h index 0ac6240dfab..da9ee2c7993 100644 --- a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h @@ -93,6 +93,20 @@ // "MyScalarCostFunction", "1, 2, 2", describe the functor as computing a // 1-dimensional output from two arguments, both 2-dimensional. // +// The autodiff cost function also supports cost functions with a +// runtime-determined number of residuals. For example: +// +// CostFunction* cost_function +// = new AutoDiffCostFunction( +// new CostFunctionWithDynamicNumResiduals(1.0), ^ ^ ^ +// runtime_number_of_residuals); <----+ | | | +// | | | | +// | | | | +// Actual number of residuals ------+ | | | +// Indicate dynamic number of residuals ---------+ | | +// Dimension of x -------------------------------------+ | +// Dimension of y ----------------------------------------+ +// // The framework can currently accommodate cost functions of up to 6 independent // variables, and there is no limit on the dimensionality of each of them. // @@ -115,18 +129,26 @@ #include "ceres/internal/autodiff.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/sized_cost_function.h" +#include "ceres/types.h" namespace ceres { -// A cost function which computes the derivative of the cost with respect to the -// parameters (a.k.a. the jacobian) using an autodifferentiation framework. The -// first template argument is the functor object, described in the header -// comment. The second argument is the dimension of the residual, and subsequent +// A cost function which computes the derivative of the cost with respect to +// the parameters (a.k.a. the jacobian) using an autodifferentiation framework. +// The first template argument is the functor object, described in the header +// comment. The second argument is the dimension of the residual (or +// ceres::DYNAMIC to indicate it will be set at runtime), and subsequent // arguments describe the size of the Nth parameter, one per parameter. // -// The constructor, which takes a cost functor, takes ownership of the functor. +// The constructors take ownership of the cost functor. +// +// If the number of residuals (argument "M" below) is ceres::DYNAMIC, then the +// two-argument constructor must be used. The second constructor takes a number +// of residuals (in addition to the templated number of residuals). This allows +// for varying the number of residuals for a single autodiff cost function at +// runtime. template { public: - // Takes ownership of functor. - explicit AutoDiffCostFunction(CostFunctor* functor) : functor_(functor) {} + // Takes ownership of functor. Uses the template-provided value for the + // number of residuals ("M"). + explicit AutoDiffCostFunction(CostFunctor* functor) + : functor_(functor) { + CHECK_NE(M, DYNAMIC) << "Can't run the fixed-size constructor if the " + << "number of residuals is set to ceres::DYNAMIC."; + } + + // Takes ownership of functor. Ignores the template-provided number of + // residuals ("M") in favor of the "num_residuals" argument provided. + // + // This allows for having autodiff cost functions which return varying + // numbers of residuals at runtime. + AutoDiffCostFunction(CostFunctor* functor, int num_residuals) + : functor_(functor) { + CHECK_EQ(M, DYNAMIC) << "Can't run the dynamic-size constructor if the " + << "number of residuals is not ceres::DYNAMIC."; + SizedCostFunction::set_num_residuals(num_residuals); + } virtual ~AutoDiffCostFunction() {} @@ -151,14 +190,16 @@ class AutoDiffCostFunction : double** jacobians) const { if (!jacobians) { return internal::VariadicEvaluate< - CostFunctor, double, M, N0, N1, N2, N3, N4, N5> + CostFunctor, double, N0, N1, N2, N3, N4, N5> ::Call(*functor_, parameters, residuals); } return internal::AutoDiff::Differentiate(*functor_, - parameters, - residuals, - jacobians); + N0, N1, N2, N3, N4, N5>::Differentiate( + *functor_, + parameters, + SizedCostFunction::num_residuals(), + residuals, + jacobians); } private: diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h index 1a9d396c9ef..4f5081f8f66 100644 --- a/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h +++ b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h @@ -144,6 +144,7 @@ #include #include "ceres/jet.h" +#include "ceres/internal/eigen.h" #include "ceres/internal/fixed_array.h" namespace ceres { @@ -185,18 +186,12 @@ inline void Take0thOrderPart(int M, const JetT *src, T dst) { // Takes N 1st order parts, starting at index N0, and puts them in the M x N // matrix 'dst'. This is used to pick out the "matrix" parts of the extended y. -template -inline void Take1stOrderPart(const JetT *src, T *dst) { +template +inline void Take1stOrderPart(const int M, const JetT *src, T *dst) { DCHECK(src); DCHECK(dst); - // TODO(keir): Change Jet to use a single array, where v[0] is the - // non-infinitesimal part rather than "a". That way it's possible to use a - // single memcpy or eigen operation, rather than the explicit loop. The loop - // doesn't exploit any SSE or other intrinsics. for (int i = 0; i < M; ++i) { - for (int j = 0; j < N; ++j) { - dst[N * i + j] = src[i].v[N0 + j]; - } + Eigen::Map >(dst + N * i, N) = src[i].v.template segment(N0); } } @@ -208,7 +203,7 @@ inline void Take1stOrderPart(const JetT *src, T *dst) { // Supporting variadic functions is the primary source of complexity in the // autodiff implementation. -template struct VariadicEvaluate { static bool Call(const Functor& functor, T const *const *input, T* output) { @@ -222,9 +217,9 @@ struct VariadicEvaluate { } }; -template -struct VariadicEvaluate { +struct VariadicEvaluate { static bool Call(const Functor& functor, T const *const *input, T* output) { return functor(input[0], input[1], @@ -235,9 +230,9 @@ struct VariadicEvaluate { } }; -template -struct VariadicEvaluate { +struct VariadicEvaluate { static bool Call(const Functor& functor, T const *const *input, T* output) { return functor(input[0], input[1], @@ -247,9 +242,9 @@ struct VariadicEvaluate { } }; -template -struct VariadicEvaluate { +struct VariadicEvaluate { static bool Call(const Functor& functor, T const *const *input, T* output) { return functor(input[0], input[1], @@ -258,9 +253,9 @@ struct VariadicEvaluate { } }; -template -struct VariadicEvaluate { +struct VariadicEvaluate { static bool Call(const Functor& functor, T const *const *input, T* output) { return functor(input[0], input[1], @@ -268,8 +263,8 @@ struct VariadicEvaluate { } }; -template -struct VariadicEvaluate { +template +struct VariadicEvaluate { static bool Call(const Functor& functor, T const *const *input, T* output) { return functor(input[0], output); @@ -279,11 +274,12 @@ struct VariadicEvaluate { // This is in a struct because default template parameters on a function are not // supported in C++03 (though it is available in C++0x). N0 through N5 are the // dimension of the input arguments to the user supplied functor. -template struct AutoDiff { static bool Differentiate(const Functor& functor, T const *const *parameters, + int num_outputs, T *function_value, T **jacobians) { typedef Jet JetT; @@ -300,10 +296,10 @@ struct AutoDiff { << "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", " << N3 << ", " << N4 << ", " << N5; - DCHECK_GT(kNumOutputs, 0); + DCHECK_GT(num_outputs, 0); FixedArray x( - N0 + N1 + N2 + N3 + N4 + N5 + kNumOutputs); + N0 + N1 + N2 + N3 + N4 + N5 + num_outputs); // It's ugly, but it works. const int jet0 = 0; @@ -339,22 +335,22 @@ struct AutoDiff { CERES_MAKE_1ST_ORDER_PERTURBATION(5); #undef CERES_MAKE_1ST_ORDER_PERTURBATION - if (!VariadicEvaluate::Call( functor, unpacked_parameters, output)) { return false; } - internal::Take0thOrderPart(kNumOutputs, output, function_value); + internal::Take0thOrderPart(num_outputs, output, function_value); #define CERES_TAKE_1ST_ORDER_PERTURBATION(i) \ if (N ## i) { \ if (jacobians[i]) { \ internal::Take1stOrderPart(output, \ - jacobians[i]); \ + N ## i>(num_outputs, \ + output, \ + jacobians[i]); \ } \ } CERES_TAKE_1ST_ORDER_PERTURBATION(0); diff --git a/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h index 968285b8f1e..2894a9fba5c 100644 --- a/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h @@ -30,11 +30,16 @@ // // A convenience class for cost functions which are statically sized. // Compared to the dynamically-sized base class, this reduces boilerplate. +// +// The kNumResiduals template parameter can be a constant such as 2 or 5, or it +// can be ceres::DYNAMIC. If kNumResiduals is ceres::DYNAMIC, then subclasses +// are responsible for calling set_num_residuals() at runtime. #ifndef CERES_PUBLIC_SIZED_COST_FUNCTION_H_ #define CERES_PUBLIC_SIZED_COST_FUNCTION_H_ #include +#include "ceres/types.h" #include "ceres/cost_function.h" namespace ceres { @@ -45,11 +50,12 @@ class SizedCostFunction : public CostFunction { public: SizedCostFunction() { // Sanity checking. - DCHECK_GT(kNumResiduals, 0) << "Cost functions must have at least " - << "one residual block."; - DCHECK_GT(N0, 0) + CHECK(kNumResiduals > 0 || kNumResiduals == DYNAMIC) + << "Cost functions must have at least one residual block."; + + CHECK_GT(N0, 0) << "Cost functions must have at least one parameter block."; - DCHECK((!N1 && !N2 && !N3 && !N4 && !N5) || + CHECK((!N1 && !N2 && !N3 && !N4 && !N5) || ((N1 > 0) && !N2 && !N3 && !N4 && !N5) || ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5) || ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5) || diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h index 15fd7332d21..bd669272023 100644 --- a/extern/libmv/third_party/ceres/include/ceres/solver.h +++ b/extern/libmv/third_party/ceres/include/ceres/solver.h @@ -83,7 +83,8 @@ class Solver { minimizer_progress_to_stdout = false; return_initial_residuals = false; return_final_residuals = false; - lsqp_dump_format = "lm_iteration_%03d.lsqp"; + lsqp_dump_directory = "/tmp"; + lsqp_dump_format_type = TEXTFILE; crash_and_dump_lsqp_on_failure = false; check_gradients = false; gradient_check_relative_precision = 1e-8; @@ -213,12 +214,8 @@ class Solver { // // This is ignored if protocol buffers are disabled. vector lsqp_iterations_to_dump; - - // Format string for the file name used for dumping the least - // squares problem to disk. If the format is 'ascii', then the - // problem is logged to the screen; don't try this with large - // problems or expect a frozen terminal. - string lsqp_dump_format; + string lsqp_dump_directory; + DumpFormatType lsqp_dump_format_type; // Dump the linear least squares problem to disk if the minimizer // fails due to NUMERICAL_FAILURE and crash the process. This flag diff --git a/extern/libmv/third_party/ceres/include/ceres/types.h b/extern/libmv/third_party/ceres/include/ceres/types.h index b83a266d1ba..a30c79029ac 100644 --- a/extern/libmv/third_party/ceres/include/ceres/types.h +++ b/extern/libmv/third_party/ceres/include/ceres/types.h @@ -210,6 +210,40 @@ enum CallbackReturnType { SOLVER_TERMINATE_SUCCESSFULLY }; +// The format in which linear least squares problems should be logged +// when Solver::Options::lsqp_iterations_to_dump is non-empty. +enum DumpFormatType { + // Print the linear least squares problem in a human readable format + // to stderr. The Jacobian is printed as a dense matrix. The vectors + // D, x and f are printed as dense vectors. This should only be used + // for small problems. + CONSOLE, + + // Write out the linear least squares problem to the directory + // pointed to by Solver::Options::lsqp_dump_directory as a protocol + // buffer. linear_least_squares_problems.h/cc contains routines for + // loading these problems. For details on the on disk format used, + // see matrix.proto. The files are named lm_iteration_???.lsqp. + PROTOBUF, + + // Write out the linear least squares problem to the directory + // pointed to by Solver::Options::lsqp_dump_directory as text files + // which can be read into MATLAB/Octave. The Jacobian is dumped as a + // text file containing (i,j,s) triplets, the vectors D, x and f are + // dumped as text files containing a list of their values. + // + // A MATLAB/octave script called lm_iteration_???.m is also output, + // which can be used to parse and load the problem into memory. + TEXTFILE +}; + +// For SizedCostFunction and AutoDiffCostFunction, DYNAMIC can be specified for +// the number of residuals. If specified, then the number of residuas for that +// cost function can vary at runtime. +enum DimensionType { + DYNAMIC = -1 +}; + const char* LinearSolverTypeToString(LinearSolverType type); const char* PreconditionerTypeToString(PreconditionerType type); const char* LinearSolverTerminationTypeToString( diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc index c1be9402b78..7dd395e2975 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc @@ -259,5 +259,28 @@ void BlockSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { } #endif +void BlockSparseMatrix::ToTextFile(FILE* file) const { + CHECK_NOTNULL(file); + for (int i = 0; i < block_structure_->rows.size(); ++i) { + const int row_block_pos = block_structure_->rows[i].block.position; + const int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + const int col_block_id = cells[j].block_id; + const int col_block_size = block_structure_->cols[col_block_id].size; + const int col_block_pos = block_structure_->cols[col_block_id].position; + int jac_pos = cells[j].position; + for (int r = 0; r < row_block_size; ++r) { + for (int c = 0; c < col_block_size; ++c) { + fprintf(file, "% 10d % 10d %17f\n", + row_block_pos + r, + col_block_pos + c, + values_[jac_pos++]); + } + } + } + } +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h index b151dd0e248..f71446e8f58 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h @@ -113,6 +113,8 @@ class BlockSparseMatrix : public BlockSparseMatrixBase { #ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS virtual void ToProto(SparseMatrixProto* proto) const; #endif + virtual void ToTextFile(FILE* file) const; + virtual int num_rows() const { return num_rows_; } virtual int num_cols() const { return num_cols_; } virtual int num_nonzeros() const { return num_nonzeros_; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc index 8fd568ffcc3..95edf5396af 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc @@ -321,5 +321,14 @@ void CompressedRowSparseMatrix::AppendRows(const CompressedRowSparseMatrix& m) { num_rows_ += m.num_rows(); } +void CompressedRowSparseMatrix::ToTextFile(FILE* file) const { + CHECK_NOTNULL(file); + for (int r = 0; r < num_rows_; ++r) { + for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) { + fprintf(file, "% 10d % 10d %17f\n", r, cols_[idx], values_[idx]); + } + } +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h index 43712a86640..9a39d28e111 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h @@ -88,7 +88,7 @@ class CompressedRowSparseMatrix : public SparseMatrix { #ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS virtual void ToProto(SparseMatrixProto* proto) const; #endif - + virtual void ToTextFile(FILE* file) const; virtual int num_rows() const { return num_rows_; } virtual int num_cols() const { return num_cols_; } virtual int num_nonzeros() const { return rows_[num_rows_]; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc index ffbfab61de1..5d392ba6c3b 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc @@ -179,6 +179,19 @@ AlignedMatrixRef DenseSparseMatrix::mutable_matrix() { return AlignedMatrixRef(m_.data(), m_.rows(), m_.cols()); } +void DenseSparseMatrix::ToTextFile(FILE* file) const { + CHECK_NOTNULL(file); + const int active_rows = + (has_diagonal_reserved_ && !has_diagonal_appended_) + ? (m_.rows() - m_.cols()) + : m_.rows(); + + for (int r = 0; r < active_rows; ++r) { + for (int c = 0; c < m_.cols(); ++c) { + fprintf(file, "% 10d % 10d %17f\n", r, c, m_(r, c)); + } + } +} } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h index 5ce29eef51b..416c2143c2c 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h @@ -70,6 +70,7 @@ class DenseSparseMatrix : public SparseMatrix { #ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS virtual void ToProto(SparseMatrixProto* proto) const; #endif + virtual void ToTextFile(FILE* file) const; virtual int num_rows() const; virtual int num_cols() const; virtual int num_nonzeros() const; diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc index 3ad359e63e4..b40a5162adc 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc @@ -58,6 +58,7 @@ #include "Eigen/Core" #include "ceres/evaluator.h" #include "ceres/file.h" +#include "ceres/linear_least_squares_problems.h" #include "ceres/linear_solver.h" #include "ceres/matrix_proto.h" #include "ceres/sparse_matrix.h" @@ -107,62 +108,6 @@ void LevenbergMarquardtDiagonal(const SparseMatrix& jacobian, } } -string DumpLinearSolverProblem( - int iteration, - const SparseMatrix* A, - const double* D, - const double* b, - const double* x, - const Minimizer::Options& solver_options) { - if (solver_options.lsqp_dump_format == "ascii") { - // Dump to the screen instead of to file. Useful for debugging. - Matrix AA; - A->ToDenseMatrix(&AA); - LOG(INFO) << "A^T: \n" << AA.transpose(); - if (D) { - LOG(INFO) << "A's appended diagonal:\n" - << ConstVectorRef(D, A->num_cols()); - } - LOG(INFO) << "b: \n" << ConstVectorRef(b, A->num_rows()); - LOG(INFO) << "x: \n" << ConstVectorRef(x, A->num_cols()); - return ""; - } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS - LinearLeastSquaresProblemProto lsqp; - A->ToProto(lsqp.mutable_a()); - for (int i = 0; i < A->num_rows(); ++i) { - lsqp.add_b(b[i]); - } - if (D) { - for (int i = 0; i < A->num_cols(); ++i) { - lsqp.add_d(D[i]); - } - } - if (x) { - for (int i = 0; i < A->num_cols(); ++i) { - lsqp.add_x(x[i]); - } - } - - lsqp.set_num_eliminate_blocks(solver_options.num_eliminate_blocks); - - CHECK(solver_options.lsqp_dump_format.size()); - string filename = - StringPrintf(solver_options.lsqp_dump_format.c_str(), // NOLINT - iteration); - VLOG(1) << "Dumping least squares problem for iteration " << iteration - << " to disk. File: " << filename; - WriteStringToFileOrDie(lsqp.SerializeAsString(), filename); - VLOG(2) << "Done dumping to disk"; - return filename; -#else - LOG(ERROR) << "Dumping least squares problems is only " - << "supported when Ceres is compiled with " - << "protocol buffer support."; - return ""; -#endif -} - bool RunCallback(IterationCallback* callback, const IterationSummary& iteration_summary, Solver::Summary* summary) { @@ -380,12 +325,17 @@ void LevenbergMarquardt::Minimize(const Minimizer::Options& options, if (binary_search(iterations_to_dump.begin(), iterations_to_dump.end(), iteration)) { - DumpLinearSolverProblem(iteration, - jacobian.get(), - muD.data(), - f.data(), - lm_step.data(), - options); + CHECK(DumpLinearLeastSquaresProblem(options.lsqp_dump_directory, + iteration, + options.lsqp_dump_format_type, + jacobian.get(), + muD.data(), + f.data(), + lm_step.data(), + options.num_eliminate_blocks)) + << "Tried writing linear least squares problem: " + << options.lsqp_dump_directory + << " but failed."; } // We ignore the case where the linear solver did not converge, @@ -413,7 +363,7 @@ void LevenbergMarquardt::Minimize(const Minimizer::Options& options, (x_norm + options.parameter_tolerance)) { summary->termination_type = PARAMETER_TOLERANCE; VLOG(1) << "Terminating on PARAMETER_TOLERANCE." - << "Relative step size: " << step_norm / step_size_tolerance + << "Relative step size: " << step_norm / step_size_tolerance << " <= " << options.parameter_tolerance; return; } @@ -545,33 +495,37 @@ void LevenbergMarquardt::Minimize(const Minimizer::Options& options, } if (num_consecutive_insane_steps == kMaxLinearSolverRetries) { - VLOG(1) << "Too many consecutive retries; ending with numerical fail."; summary->termination_type = NUMERICAL_FAILURE; + VLOG(1) << "Too many consecutive retries; ending with numerical fail."; if (!options.crash_and_dump_lsqp_on_failure) { return; } // Dump debugging information to disk. - CHECK(!options.lsqp_dump_format.empty()) + CHECK(options.lsqp_dump_format_type == TEXTFILE || + options.lsqp_dump_format_type == PROTOBUF) << "Dumping the linear least squares problem on crash " - << "requires Solver::Options::lsqp_dump_format set a " - << "filename"; - CHECK_NE(options.lsqp_dump_format, "ascii") - << "Dumping the linear least squares problem on crash " - << "requires Solver::Options::lsqp_dump_format set a " - << "filename"; + << "requires Solver::Options::lsqp_dump_format_type to be " + << "PROTOBUF or TEXTFILE."; - const string filename = DumpLinearSolverProblem(iteration, - jacobian.get(), - muD.data(), - f.data(), - lm_step.data(), - options); - LOG(FATAL) << "Linear least squares problem saved to " << filename - << " please provide this to the Ceres developers for " - << " debugging along with the v=2 log."; - return; + if (DumpLinearLeastSquaresProblem(options.lsqp_dump_directory, + iteration, + options.lsqp_dump_format_type, + jacobian.get(), + muD.data(), + f.data(), + lm_step.data(), + options.num_eliminate_blocks)) { + LOG(FATAL) << "Linear least squares problem saved to: " + << options.lsqp_dump_directory + << ". Please provide this to the Ceres developers for " + << " debugging along with the v=2 log."; + } else { + LOG(FATAL) << "Tried writing linear least squares problem: " + << options.lsqp_dump_directory + << " but failed."; + } } if (!step_is_successful) { diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc index 9fc5ff8a1c7..cca9f442fe7 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc @@ -30,15 +30,18 @@ #include "ceres/linear_least_squares_problems.h" +#include #include #include #include #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" +#include "ceres/casts.h" #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/file.h" #include "ceres/matrix_proto.h" #include "ceres/triplet_sparse_matrix.h" +#include "ceres/stringprintf.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" @@ -570,5 +573,172 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() { return problem; } +bool DumpLinearLeastSquaresProblemToConsole(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + CHECK_NOTNULL(A); + Matrix AA; + A->ToDenseMatrix(&AA); + LOG(INFO) << "A^T: \n" << AA.transpose(); + + if (D != NULL) { + LOG(INFO) << "A's appended diagonal:\n" + << ConstVectorRef(D, A->num_cols()); + } + + if (b != NULL) { + LOG(INFO) << "b: \n" << ConstVectorRef(b, A->num_rows()); + } + + if (x != NULL) { + LOG(INFO) << "x: \n" << ConstVectorRef(x, A->num_cols()); + } + return true; +}; + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + CHECK_NOTNULL(A); + LinearLeastSquaresProblemProto lsqp; + A->ToProto(lsqp.mutable_a()); + + if (D != NULL) { + for (int i = 0; i < A->num_cols(); ++i) { + lsqp.add_d(D[i]); + } + } + + if (b != NULL) { + for (int i = 0; i < A->num_rows(); ++i) { + lsqp.add_b(b[i]); + } + } + + if (x != NULL) { + for (int i = 0; i < A->num_cols(); ++i) { + lsqp.add_x(x[i]); + } + } + + lsqp.set_num_eliminate_blocks(num_eliminate_blocks); + string format_string = JoinPath(directory, + "lm_iteration_%03d.lsqp"); + string filename = + StringPrintf(format_string.c_str(), iteration); + LOG(INFO) << "Dumping least squares problem for iteration " << iteration + << " to disk. File: " << filename; + WriteStringToFileOrDie(lsqp.SerializeAsString(), filename); + return true; +} +#else +bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + LOG(ERROR) << "Dumping least squares problems is only " + << "supported when Ceres is compiled with " + << "protocol buffer support."; + return false; +} +#endif + +void WriteArrayToFileOrDie(const string& filename, + const double* x, + const int size) { + CHECK_NOTNULL(x); + VLOG(2) << "Writing array to: " << filename; + FILE* fptr = fopen(filename.c_str(), "w"); + CHECK_NOTNULL(fptr); + for (int i = 0; i < size; ++i) { + fprintf(fptr, "%17f\n", x[i]); + } + fclose(fptr); +} + +bool DumpLinearLeastSquaresProblemToTextFile(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + CHECK_NOTNULL(A); + string format_string = JoinPath(directory, + "lm_iteration_%03d"); + string filename_prefix = + StringPrintf(format_string.c_str(), iteration); + + { + string filename = filename_prefix + "_A.txt"; + LOG(INFO) << "writing to: " << filename; + FILE* fptr = fopen(filename.c_str(), "w"); + CHECK_NOTNULL(fptr); + A->ToTextFile(fptr); + fclose(fptr); + } + + if (D != NULL) { + string filename = filename_prefix + "_D.txt"; + WriteArrayToFileOrDie(filename, D, A->num_cols()); + } + + if (b != NULL) { + string filename = filename_prefix + "_b.txt"; + WriteArrayToFileOrDie(filename, b, A->num_rows()); + } + + if (x != NULL) { + string filename = filename_prefix + "_x.txt"; + WriteArrayToFileOrDie(filename, x, A->num_cols()); + } + + return true; +} + +bool DumpLinearLeastSquaresProblem(const string& directory, + int iteration, + DumpFormatType dump_format_type, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + switch (dump_format_type) { + case (CONSOLE): + return DumpLinearLeastSquaresProblemToConsole(directory, + iteration, + A, D, b, x, + num_eliminate_blocks); + case (PROTOBUF): + return DumpLinearLeastSquaresProblemToProtocolBuffer( + directory, + iteration, + A, D, b, x, + num_eliminate_blocks); + case (TEXTFILE): + return DumpLinearLeastSquaresProblemToTextFile(directory, + iteration, + A, D, b, x, + num_eliminate_blocks); + default: + LOG(FATAL) << "Unknown DumpFormatType " << dump_format_type; + }; + + return true; +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h index 46a624bd73f..553cc0d3db3 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h @@ -32,7 +32,7 @@ #define CERES_INTERNAL_LINEAR_LEAST_SQUARES_PROBLEMS_H_ #include - +#include #include "ceres/sparse_matrix.h" #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" @@ -71,6 +71,16 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem1(); LinearLeastSquaresProblem* LinearLeastSquaresProblem2(); LinearLeastSquaresProblem* LinearLeastSquaresProblem3(); +// Write the linear least squares problem to disk. The exact format +// depends on dump_format_type. +bool DumpLinearLeastSquaresProblem(const string& directory, + int iteration, + DumpFormatType dump_format_type, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks); } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h index 71163a8ea6f..77cb00cb6b4 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h +++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h @@ -59,8 +59,9 @@ class Minimizer { tau = options.tau; jacobi_scaling = options.jacobi_scaling; crash_and_dump_lsqp_on_failure = options.crash_and_dump_lsqp_on_failure; - lsqp_dump_format = options.lsqp_dump_format; + lsqp_dump_directory = options.lsqp_dump_directory; lsqp_iterations_to_dump = options.lsqp_iterations_to_dump; + lsqp_dump_format_type = options.lsqp_dump_format_type; num_eliminate_blocks = options.num_eliminate_blocks; logging_type = options.logging_type; } @@ -75,8 +76,9 @@ class Minimizer { double tau; bool jacobi_scaling; bool crash_and_dump_lsqp_on_failure; - string lsqp_dump_format; vector lsqp_iterations_to_dump; + DumpFormatType lsqp_dump_format_type; + string lsqp_dump_directory; int num_eliminate_blocks; LoggingType logging_type; diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h index 962b803dd87..562210dfec8 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h @@ -33,6 +33,7 @@ #ifndef CERES_INTERNAL_SPARSE_MATRIX_H_ #define CERES_INTERNAL_SPARSE_MATRIX_H_ +#include #include "ceres/linear_operator.h" #include "ceres/internal/eigen.h" #include "ceres/types.h" @@ -87,9 +88,14 @@ class SparseMatrix : public LinearOperator { #ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS // Dump the sparse matrix to a proto. Destroys the contents of proto. - virtual void ToProto(SparseMatrixProto *proto) const = 0; + virtual void ToProto(SparseMatrixProto* proto) const = 0; #endif + // Write out the matrix as a sequence of (i,j,s) triplets. This + // format is useful for loading the matrix into MATLAB/octave as a + // sparse matrix. + virtual void ToTextFile(FILE* file) const = 0; + // Accessors for the values array that stores the entries of the // sparse matrix. The exact interpreptation of the values of this // array depends on the particular kind of SparseMatrix being diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc index 7d7c3df9960..247ab2e697b 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc @@ -295,5 +295,12 @@ TripletSparseMatrix* TripletSparseMatrix::CreateSparseDiagonalMatrix( return m; } +void TripletSparseMatrix::ToTextFile(FILE* file) const { + CHECK_NOTNULL(file); + for (int i = 0; i < num_nonzeros_; ++i) { + fprintf(file, "% 10d % 10d %17f\n", rows_[i], cols_[i], values_[i]); + } +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h index 3c90a62fd20..300e74d0bbc 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h @@ -68,6 +68,7 @@ class TripletSparseMatrix : public SparseMatrix { #ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS virtual void ToProto(SparseMatrixProto *proto) const; #endif + virtual void ToTextFile(FILE* file) const; virtual int num_rows() const { return num_rows_; } virtual int num_cols() const { return num_cols_; } virtual int num_nonzeros() const { return num_nonzeros_; } diff --git a/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch b/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch new file mode 100644 index 00000000000..c3129d8e02b --- /dev/null +++ b/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch @@ -0,0 +1,15 @@ +diff --git a/internal/ceres/residual_block_utils.cc b/internal/ceres/residual_block_utils.cc +index ed3499b..28e0313 100644 +--- a/internal/ceres/residual_block_utils.cc ++++ b/internal/ceres/residual_block_utils.cc +@@ -40,6 +40,10 @@ + #include "ceres/internal/eigen.h" + #include "ceres/internal/port.h" + ++#ifdef _MSC_VER ++# define isfinite _finite ++#endif ++ + namespace ceres { + namespace internal { + From 39e81b468da264e1650fdbb634853126571e55c2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 10 May 2012 11:39:08 +0000 Subject: [PATCH 029/183] Tomato: ceres bundling script now works on svn checkout --- extern/libmv/third_party/ceres/bundle.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh index d7602f7c171..f54342180db 100755 --- a/extern/libmv/third_party/ceres/bundle.sh +++ b/extern/libmv/third_party/ceres/bundle.sh @@ -1,7 +1,9 @@ #!/bin/sh -if [ -d ./.svn ]; then - echo "This script is supposed to work only when using git-svn" +if [ "x$1" = "x--i-really-know-what-im-doing" ] ; then + echo Proceeding as requested by command line ... +else + echo "*** Please run again with --i-really-know-what-im-doing ..." exit 1 fi @@ -24,8 +26,8 @@ for p in `cat ./patches/series`; do cat ./patches/$p | patch -d $tmp/ceres -p1 done -rm -rf include -rm -rf internal +find include -type f -not -iwholename '*.svn*' -exec rm -rf {} \; +find internal -type f -not -iwholename '*.svn*' -exec rm -rf {} \; cat "files.txt" | while read f; do mkdir -p `dirname $f` From e345a232d8dcb2838be54ddc074bd91bfee58a3d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 11 May 2012 05:21:04 +0000 Subject: [PATCH 030/183] Tomato: fixed invalid float suffix. --- source/blender/editors/mask/mask_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 0fedc2b34dc..acfd633a811 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -94,7 +94,7 @@ static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, fl float u = -1.0f, du = 1.0f / N, u1 = start_u, u2 = start_u; float ang = -1.0f; - while (u1 > 0.0f || u2 < 1.0d) { + while (u1 > 0.0f || u2 < 1.0f) { float n1[2], n2[2], co1[2], co2[2]; float v1[2], v2[2]; float ang1, ang2; From b3c1c03ba4f3f93f0df4e62d277995a3e5794646 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 13 May 2012 16:24:42 +0000 Subject: [PATCH 031/183] style cleanup: mask files --- source/blender/blenkernel/BKE_mask.h | 26 ++++++++++--------- source/blender/blenkernel/intern/mask.c | 25 +++++++++--------- .../composite/nodes/node_composite_mask.c | 8 +++--- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 268b7df0247..b39e15b4d32 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -53,20 +53,22 @@ struct MaskSpline *BKE_mask_spline_add(struct MaskShape *shape); int BKE_mask_spline_resolution(struct MaskSpline *spline); float *BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point); float *BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, float aspx, - float aspy, int *tot_feather_point); + float aspy, int *tot_feather_point); float *BKE_mask_spline_feather_points(struct MaskSpline *spline, float aspx, float aspy, int *tot_feather_point); /* point */ int BKE_mask_point_has_handle(struct MaskSplinePoint *point); void BKE_mask_point_handle(struct MaskSplinePoint *point, float aspx, float aspy, float handle[2]); -void BKE_mask_point_set_handle(struct MaskSplinePoint *point, float loc[2], int keep_direction, float aspx, float aspy, float orig_handle[2], float orig_vec[3][3]); +void BKE_mask_point_set_handle(struct MaskSplinePoint *point, float loc[2], int keep_direction, + float aspx, float aspy, float orig_handle[2], float orig_vec[3][3]); float *BKE_mask_point_segment_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, int *tot_diff_point); float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, float aspx, float aspy, int *tot_feather_point); void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2]); -void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, float aspx, float aspy, float u, float n[2]); +void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, + float aspx, float aspy, float u, float n[2]); float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *point, float u); -struct MaskSplinePointUW * BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw); +struct MaskSplinePointUW *BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw); void BKE_mask_point_add_uw(struct MaskSplinePoint *point, float u, float w); /* general */ @@ -81,15 +83,15 @@ void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime); void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene); void BKE_mask_parent_init(struct MaskParent *parent); -#define MASKPOINT_ISSEL(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT ) -#define MASKPOINT_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } -#define MASKPOINT_DESEL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } -#define MASKPOINT_INVSEL(p) { (p)->bezt.f1 ^= SELECT; (p)->bezt.f2 ^= SELECT; (p)->bezt.f3 ^= SELECT; } +#define MASKPOINT_ISSEL(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT ) +#define MASKPOINT_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 +#define MASKPOINT_DESEL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 +#define MASKPOINT_INVSEL(p) { (p)->bezt.f1 ^= SELECT; (p)->bezt.f2 ^= SELECT; (p)->bezt.f3 ^= SELECT; } (void)0 -#define MASKPOINT_CV_ISSEL(p) ( (p)->bezt.f2 & SELECT ) +#define MASKPOINT_CV_ISSEL(p) ( (p)->bezt.f2 & SELECT ) -#define MASKPOINT_HANDLE_ONLY_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT ) && (((p)->bezt.f2 & SELECT) == 0) ) -#define MASKPOINT_HANDLE_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT ) ) -#define MASKPOINT_HANDLE_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f3 |= SELECT; } +#define MASKPOINT_HANDLE_ONLY_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) && (((p)->bezt.f2 & SELECT) == 0) ) +#define MASKPOINT_HANDLE_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) ) +#define MASKPOINT_HANDLE_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 #endif diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index d359cd077af..55dab26b841 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -217,7 +217,7 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) /* len+1 because of 'forward_diff_bezier' function */ *tot_diff_point = len; - diff_points = fp = MEM_callocN((len + 1)*2*sizeof(float), "mask spline vets"); + diff_points = fp = MEM_callocN((len + 1) * 2 * sizeof(float), "mask spline vets"); a = spline->tot_point - 1; if (spline->flag & MASK_SPLINE_CYCLIC) @@ -231,7 +231,7 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) BezTriple *bezt; int j; - if (a==0 && (spline->flag & MASK_SPLINE_CYCLIC)) + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) point = spline->points; prevbezt = &prev->bezt; @@ -245,7 +245,7 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) fp += 2 * resol; - if (a==0 && (spline->flag & MASK_SPLINE_CYCLIC)==0) { + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { copy_v2_v2(fp, bezt->vec[1]); } @@ -257,7 +257,7 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) } float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, float aspx, float aspy, - int *tot_feather_point) + int *tot_feather_point) { float *feather, *fp; int i, j, tot, resol = BKE_mask_spline_feather_resolution(spline); @@ -352,8 +352,8 @@ void BKE_mask_point_handle(MaskSplinePoint *point, float aspx, float aspy, float vec[0] *= aspx; vec[1] *= aspy; - handle[0] = (point->bezt.vec[1][0]*aspx + vec[1]) / aspx; - handle[1] = (point->bezt.vec[1][1]*aspy - vec[0]) / aspy; + handle[0] = (point->bezt.vec[1][0] * aspx + vec[1]) / aspx; + handle[1] = (point->bezt.vec[1][1] * aspy - vec[0]) / aspy; } void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_direction, float aspx, float aspy, @@ -393,7 +393,8 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di copy_v3_v3(bezt->vec[0], bezt->vec[1]); copy_v3_v3(bezt->vec[2], bezt->vec[1]); } - } else { + } + else { sub_v2_v2v2(v1, loc, bezt->vec[1]); v2[0] = -v1[1] * aspy / aspx; @@ -450,7 +451,7 @@ float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, i /* resol+1 because of 'forward_diff_bezier' function */ *tot_diff_point = resol + 1; - diff_points = fp = MEM_callocN((resol + 1)*2*sizeof(float), "mask segment vets"); + diff_points = fp = MEM_callocN((resol + 1) * 2 * sizeof(float), "mask segment vets"); for (j = 0; j < 2; j++) { BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j], @@ -712,18 +713,18 @@ void BKE_mask_unlink(Main *bmain, Mask *mask) for (scr = bmain->screen.first; scr; scr = scr->id.next) { for (area = scr->areabase.first; area; area = area->next) { - for(sl = area->spacedata.first; sl; sl = sl->next) { - if(sl->spacetype == SPACE_CLIP) { + for (sl = area->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { SpaceClip *sc = (SpaceClip *) sl; - if(sc->mask == mask) + if (sc->mask == mask) sc->mask = NULL; } } } } - mask->id.us= 0; + mask->id.us = 0; } static void evaluate_mask_parent(MaskParent *parent, float ctime, float co[2]) diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c index 2c49be48f7d..1dbe057a869 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mask.c +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -43,13 +43,13 @@ /* **************** Translate ******************** */ static bNodeSocketTemplate cmp_node_mask_in[] = { - { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - { -1, 0, "" } + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } }; static bNodeSocketTemplate cmp_node_mask_out[] = { - { SOCK_RGBA, 0, "Image"}, - { -1, 0, "" } + { SOCK_RGBA, 0, "Image"}, + { -1, 0, "" } }; static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) From 7444613a9a2ff8433712b2dc0525ee91a44c04a7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 13 May 2012 16:51:17 +0000 Subject: [PATCH 032/183] fix for crash when no mask exists when entering mask transform. --- source/blender/editors/transform/transform_conversions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 472e3ae0d1a..3d8e82eeb2f 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5868,7 +5868,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) TransDataMasking *tdm = NULL; /* count */ - shape = mask->shapes.first; + shape = mask ? mask->shapes.first : NULL; while (shape) { MaskSpline *spline = shape->splines.first; From ee9d9f4737ebebcb26ea7c9c3b8e0896f7e6b4db Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 13 May 2012 21:36:42 +0000 Subject: [PATCH 033/183] style cleanup: mask, whitespace edits, also use len_squared_v2 for comparisons. --- intern/raskter/raskter.c | 236 +++++++++--------- intern/raskter/raskter.h | 10 +- source/blender/blenkernel/BKE_mask.h | 4 +- source/blender/blenkernel/intern/idcode.c | 2 +- source/blender/blenkernel/intern/library.c | 2 +- source/blender/editors/include/ED_screen.h | 2 +- source/blender/editors/include/ED_transform.h | 2 +- source/blender/editors/mask/mask_draw.c | 32 ++- source/blender/editors/mask/mask_editor.c | 6 +- source/blender/editors/mask/mask_ops.c | 112 +++++---- 10 files changed, 213 insertions(+), 195 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 0839e8a09c2..afa8b2102ae 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -32,8 +32,8 @@ #include "raskter.h" // from BLI_utildefines.h -#define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) -#define MAX2(x,y) ( (x)>(y) ? (x) : (y) ) +#define MIN2(x, y) ( (x) < (y) ? (x) : (y) ) +#define MAX2(x, y) ( (x) > (y) ? (x) : (y) ) struct e_status { @@ -64,7 +64,7 @@ static struct r_buffer_stats rb; * just the poly. Since the DEM code could end up being coupled with this, we'll keep it separate * for now. */ -static void preprocess_all_edges(struct poly_vert * verts, int num_verts, struct e_status * open_edge) { +static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct e_status *open_edge) { int i; int xbeg; int ybeg; @@ -82,21 +82,22 @@ static void preprocess_all_edges(struct poly_vert * verts, int num_verts, struct v = verts; all_edges = NULL; // loop all verts - for(i = 0; i < num_verts; i++) { + for (i = 0; i < num_verts; i++) { // determine beginnings and endings of edges, linking last vertex to first vertex xbeg = v[i].x; ybeg = v[i].y; - if(i) { + if (i) { // we're not at the last vert, so end of the edge is the previous vertex - xend = v[i-1].x; - yend = v[i-1].y; - } else { + xend = v[i - 1].x; + yend = v[i - 1].y; + } + else { // we're at the first vertex, so the "end" of this edge is the last vertex - xend = v[num_verts-1].x; - yend = v[num_verts-1].y; + xend = v[num_verts - 1].x; + yend = v[num_verts - 1].y; } // make sure our edges are facing the correct direction - if(ybeg > yend) { + if (ybeg > yend) { // flip the Xs temp_pos = xbeg; xbeg = xend; @@ -110,16 +111,17 @@ static void preprocess_all_edges(struct poly_vert * verts, int num_verts, struct // calculate y delta dy = yend - ybeg; // dont draw horizontal lines directly, they are scanned as part of the edges they connect, so skip em. :) - if(dy) { + if (dy) { // create the edge and determine it's slope (for incremental line drawing) e_new = open_edge++; // calculate x delta dx = xend - xbeg; - if(dx > 0){ + if (dx > 0) { e_new->xdir = 1; xdist = dx; - }else{ + } + else { e_new->xdir = -1; xdist = -dx; } @@ -130,23 +132,25 @@ static void preprocess_all_edges(struct poly_vert * verts, int num_verts, struct e_new->drift_dec = dy; // calculate deltas for incremental drawing - if(dx >= 0) { + if (dx >= 0) { e_new->drift = 0; - } else { + } + else { e_new->drift = -dy + 1; } - if(dy >= xdist) { + if (dy >= xdist) { e_new->drift_inc = xdist; e_new->xshift = 0; - } else { + } + else { e_new->drift_inc = xdist % dy; e_new->xshift = (xdist / dy) * e_new->xdir; } next_edge_ref = &all_edges; // link in all the edges, in sorted order - for(;;) { + for (;; ) { next_edge = *next_edge_ref; - if(!next_edge || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) { + if (!next_edge || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) { e_new->e_next = next_edge; *next_edge_ref = e_new; break; @@ -162,156 +166,158 @@ static void preprocess_all_edges(struct poly_vert * verts, int num_verts, struct * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need * if it ends up being coupled with this function. */ -int rast_scan_fill(struct poly_vert * verts, int num_verts) { - int x_curr; // current pixel position in X - int y_curr; // current scan line being drawn - int yp; // y-pixel's position in frame buffer - int swixd = 0; // whether or not edges switched position in X - float *cpxl; // pixel pointers... +int rast_scan_fill(struct poly_vert *verts, int num_verts) { + int x_curr; // current pixel position in X + int y_curr; // current scan line being drawn + int yp; // y-pixel's position in frame buffer + int swixd = 0; // whether or not edges switched position in X + float *cpxl; // pixel pointers... float *mpxl; float *spxl; - struct e_status *e_curr; // edge pointers... + struct e_status *e_curr; // edge pointers... struct e_status *e_temp; struct e_status *edgbuf; struct e_status **edgec; /* - If the number of verts specified to render as a polygon is less than 3, - return immediately. Obviously we cant render a poly with sides < 3. The - return for this we set to 1, simply so it can be distinguished from the - next place we could return, which is a failure to allocate memory. + If the number of verts specified to render as a polygon is less than 3, + return immediately. Obviously we cant render a poly with sides < 3. The + return for this we set to 1, simply so it can be distinguished from the + next place we could return, which is a failure to allocate memory. */ - if(num_verts < 3) { + if (num_verts < 3) { return(1); } /* - Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data - multiplied by the number of edges, which is always equal to the number of verts in - a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for - the preceeding error, which was a rasterization request on a 2D poly with less than - 3 sides. + Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data + multiplied by the number of edges, which is always equal to the number of verts in + a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for + the preceeding error, which was a rasterization request on a 2D poly with less than + 3 sides. */ - if((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_verts))) == NULL) { + if ((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_verts))) == NULL) { return(0); } /* - Do some preprocessing on all edges. This constructs a table structure in memory of all - the edge properties and can "flip" some edges so sorting works correctly. + Do some preprocessing on all edges. This constructs a table structure in memory of all + the edge properties and can "flip" some edges so sorting works correctly. */ preprocess_all_edges(verts, num_verts, edgbuf); /* - Set the pointer for tracking the edges currently in processing to NULL to make sure - we don't get some crazy value after initialization. + Set the pointer for tracking the edges currently in processing to NULL to make sure + we don't get some crazy value after initialization. */ possible_edges = NULL; /* - Loop through all scan lines to be drawn. Since we sorted by Y values during - preprocess_all_edges(), we can already exact values for the lowest and - highest Y values we could possibly need by induction. The preprocessing sorted - out edges by Y position, we can cycle the current edge being processed once - it runs out of Y pixels. When we have no more edges, meaning the current edge - is NULL after setting the "current" edge to be the previous current edge's - "next" edge in the Y sorted edge connection chain, we can stop looping Y values, - since we can't possibly have more scan lines if we ran out of edges. :) + Loop through all scan lines to be drawn. Since we sorted by Y values during + preprocess_all_edges(), we can already exact values for the lowest and + highest Y values we could possibly need by induction. The preprocessing sorted + out edges by Y position, we can cycle the current edge being processed once + it runs out of Y pixels. When we have no more edges, meaning the current edge + is NULL after setting the "current" edge to be the previous current edge's + "next" edge in the Y sorted edge connection chain, we can stop looping Y values, + since we can't possibly have more scan lines if we ran out of edges. :) - TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. - Will get changed once DEM code gets in. + TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. + Will get changed once DEM code gets in. */ - for(y_curr = MAX2(all_edges->ybeg,0); (all_edges || possible_edges) && (y_curr < rb.sizey); y_curr++) { + for (y_curr = MAX2(all_edges->ybeg, 0); (all_edges || possible_edges) && (y_curr < rb.sizey); y_curr++) { /* - Link any edges that start on the current scan line into the list of - edges currently needed to draw at least this, if not several, scan lines. + Link any edges that start on the current scan line into the list of + edges currently needed to draw at least this, if not several, scan lines. */ /* - Set the current edge to the beginning of the list of edges to be rasterized - into this scan line. + Set the current edge to the beginning of the list of edges to be rasterized + into this scan line. - We could have lots of edge here, so iterate over all the edges needed. The - preprocess_all_edges() function sorted edges by X within each chunk of Y sorting - so we safely cycle edges to thier own "next" edges in order. + We could have lots of edge here, so iterate over all the edges needed. The + preprocess_all_edges() function sorted edges by X within each chunk of Y sorting + so we safely cycle edges to thier own "next" edges in order. - At each iteration, make sure we still have a non-NULL edge. + At each iteration, make sure we still have a non-NULL edge. */ - for(edgec = &possible_edges; all_edges && (all_edges->ybeg == y_curr);) { + for (edgec = &possible_edges; all_edges && (all_edges->ybeg == y_curr); ) { x_curr = all_edges->x; // Set current X position. - for(;;) { // Start looping edges. Will break when edges run out. + for (;; ) { // Start looping edges. Will break when edges run out. e_curr = *edgec; // Set up a current edge pointer. - if(!e_curr || (e_curr->x >= x_curr)) { // If we have an no edge, or we need to skip some X-span, + if (!e_curr || (e_curr->x >= x_curr)) { // If we have an no edge, or we need to skip some X-span, e_temp = all_edges->e_next; // set a temp "next" edge to test. *edgec = all_edges; // Add this edge to the list to be scanned. all_edges->e_next = e_curr; // Set up the next edge. edgec = &all_edges->e_next; // Set our list to the next edge's location in memory. all_edges = e_temp; // Skip the NULL or bad X edge, set pointer to next edge. break; // Stop looping edges (since we ran out or hit empty X span. - } else { + } + else { edgec = &e_curr->e_next; // Set the pointer to the edge list the "next" edge. } } } /* - Determine the current scan line's offset in the pixel buffer based on its Y position. - Basically we just multiply the current scan line's Y value by the number of pixels in each line. + Determine the current scan line's offset in the pixel buffer based on its Y position. + Basically we just multiply the current scan line's Y value by the number of pixels in each line. */ yp = y_curr * rb.sizex; /* - Set a "scan line pointer" in memory. The location of the buffer plus the row offset. + Set a "scan line pointer" in memory. The location of the buffer plus the row offset. */ spxl = rb.buf + (yp); /* - Set up the current edge to the first (in X) edge. The edges which could possibly be in this - list were determined in the preceeding edge loop above. They were already sorted in X by the - initial processing function. + Set up the current edge to the first (in X) edge. The edges which could possibly be in this + list were determined in the preceeding edge loop above. They were already sorted in X by the + initial processing function. - At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge - we will eventually hit a NULL when the list runs out. + At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge + we will eventually hit a NULL when the list runs out. */ - for(e_curr = possible_edges; e_curr; e_curr = e_curr->e_next) { + for (e_curr = possible_edges; e_curr; e_curr = e_curr->e_next) { /* - Calculate a span of pixels to fill on the current scan line. + Calculate a span of pixels to fill on the current scan line. - Set the current pixel pointer by adding the X offset to the scan line's start offset. - Cycle the current edge the next edge. - Set the max X value to draw to be one less than the next edge's first pixel. This way we are - sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than - one time because it's on a vertex connecting two edges) + Set the current pixel pointer by adding the X offset to the scan line's start offset. + Cycle the current edge the next edge. + Set the max X value to draw to be one less than the next edge's first pixel. This way we are + sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than + one time because it's on a vertex connecting two edges) - Then blast through all the pixels in the span, advancing the pointer and setting the color to white. + Then blast through all the pixels in the span, advancing the pointer and setting the color to white. - TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, - but for now it is done here until the DEM code comes in. - */ + TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, + but for now it is done here until the DEM code comes in. + */ // set up xmin and xmax bounds on this scan line - cpxl = spxl + MAX2(e_curr->x,0); + cpxl = spxl + MAX2(e_curr->x, 0); e_curr = e_curr->e_next; - mpxl = spxl + MIN2(e_curr->x,rb.sizex) - 1; + mpxl = spxl + MIN2(e_curr->x, rb.sizex) - 1; // draw the pixels. - for(; cpxl <= mpxl; *cpxl++ = 1.0f); + for (; cpxl <= mpxl; *cpxl++ = 1.0f) ; } /* - Loop through all edges of polygon that could be hit by this scan line, - and figure out their x-intersections with the next scan line. + Loop through all edges of polygon that could be hit by this scan line, + and figure out their x-intersections with the next scan line. - Either A.) we wont have any more edges to test, or B.) we just add on the - slope delta computed in preprocessing step. Since this draws non-antialiased - polygons, we dont have fractional positions, so we only move in x-direction - when needed to get all the way to the next pixel over... + Either A.) we wont have any more edges to test, or B.) we just add on the + slope delta computed in preprocessing step. Since this draws non-antialiased + polygons, we dont have fractional positions, so we only move in x-direction + when needed to get all the way to the next pixel over... */ - for(edgec = &possible_edges; (e_curr = *edgec);) { - if(!(--(e_curr->num))) { + for (edgec = &possible_edges; (e_curr = *edgec); ) { + if (!(--(e_curr->num))) { *edgec = e_curr->e_next; - } else { + } + else { e_curr->x += e_curr->xshift; - if((e_curr->drift += e_curr->drift_inc) > 0) { + if ((e_curr->drift += e_curr->drift_inc) > 0) { e_curr->x += e_curr->xdir; e_curr->drift -= e_curr->drift_dec; } @@ -319,17 +325,17 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { } } /* - It's possible that some edges may have crossed during the last step, so we'll be sure - that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges - sorted by x-intersection coordinate. We'll always scan through at least once to see if - edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial - pass, then we know we need to sort by x, so then cycle through edges again and perform - the sort.- + It's possible that some edges may have crossed during the last step, so we'll be sure + that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges + sorted by x-intersection coordinate. We'll always scan through at least once to see if + edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial + pass, then we know we need to sort by x, so then cycle through edges again and perform + the sort.- */ - if(possible_edges) { - for(edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + if (possible_edges) { + for (edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { // if the current edge hits scan line at greater X than the next edge, we need to exchange the edges - if(e_curr->x > e_curr->e_next->x) { + if (e_curr->x > e_curr->e_next->x) { *edgec = e_curr->e_next; // exchange the pointers e_temp = e_curr->e_next->e_next; @@ -340,12 +346,12 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { } } // if we did have a switch, look for more (there will more if there was one) - for(;;) { + for (;; ) { // reset exchange flag so it's only set if we encounter another one swixd = 0; - for(edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + for (edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { // again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag - if(e_curr->x > e_curr->e_next->x) { + if (e_curr->x > e_curr->e_next->x) { *edgec = e_curr->e_next; // exchange the pointers e_temp = e_curr->e_next->e_next; @@ -356,7 +362,7 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { } } // if we had no exchanges, we're done reshuffling the pointers - if(!swixd) { + if (!swixd) { break; } } @@ -367,7 +373,7 @@ int rast_scan_fill(struct poly_vert * verts, int num_verts) { return 1; } -int PLX_raskterize(float * verts, int num, float * buf, int buf_x, int buf_y) { +int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { int i; // i: Loop counter. struct poly_vert *ply; // ply: Pointer to a list of integer buffer-space vertex coordinates. @@ -378,7 +384,7 @@ int PLX_raskterize(float * verts, int num, float * buf, int buf_x, int buf_y) { * In the event of a failure to allocate the memory, return 0, so this error can * be distinguished as a memory allocation error. */ - if((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num))) == NULL) { + if ((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num))) == NULL) { return(0); } @@ -390,9 +396,9 @@ int PLX_raskterize(float * verts, int num, float * buf, int buf_x, int buf_y) { * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel * drawn will be 1.0f in value, there is no anti-aliasing. */ - for(i = 0; i < num; i++) { // Loop over all verts. - ply[i].x = (verts[i<<1] * buf_x) + 0.5f; // Range expand normalized X to integer buffer-space X. - ply[i].y = (verts[(i<<1)+1] * buf_y) + 0.5f; // Range expand normalized Y to integer buffer-space Y. + for (i = 0; i < num; i++) { // Loop over all verts. + ply[i].x = (verts[i << 1] * buf_x) + 0.5f; // Range expand normalized X to integer buffer-space X. + ply[i].y = (verts[(i << 1) + 1] * buf_y) + 0.5f; // Range expand normalized Y to integer buffer-space Y. } rb.buf = buf; // Set the output buffer pointer. diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h index 0b3cf365ff4..98aaf0f6885 100644 --- a/intern/raskter/raskter.h +++ b/intern/raskter/raskter.h @@ -28,27 +28,27 @@ * \ingroup RASKTER */ -struct poly_vert{ +struct poly_vert { int x; int y; }; -struct scan_line{ +struct scan_line { int xstart; int xend; }; -struct scan_line_batch{ +struct scan_line_batch { int num; int ystart; - struct scan_line * slines; + struct scan_line *slines; }; #ifdef __cplusplus extern "C" { #endif -int PLX_raskterize(float * verts, int num, float * buf, int buf_x, int buf_y); +int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index b39e15b4d32..31a872b5056 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -83,12 +83,12 @@ void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime); void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene); void BKE_mask_parent_init(struct MaskParent *parent); -#define MASKPOINT_ISSEL(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT ) +#define MASKPOINT_ISSEL(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) #define MASKPOINT_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 #define MASKPOINT_DESEL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 #define MASKPOINT_INVSEL(p) { (p)->bezt.f1 ^= SELECT; (p)->bezt.f2 ^= SELECT; (p)->bezt.f3 ^= SELECT; } (void)0 -#define MASKPOINT_CV_ISSEL(p) ( (p)->bezt.f2 & SELECT ) +#define MASKPOINT_CV_ISSEL(p) ( (p)->bezt.f2 & SELECT) #define MASKPOINT_HANDLE_ONLY_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) && (((p)->bezt.f2 & SELECT) == 0) ) #define MASKPOINT_HANDLE_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) ) diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 267fa732191..30427a81c4b 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -79,7 +79,7 @@ static IDType idtypes[] = { { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE}, { ID_WM, "WindowManager", "window_managers", 0}, { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE}, + { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE}, }; static int nidtypes = sizeof(idtypes) / sizeof(idtypes[0]); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index a4326a0cb72..0aae210dd17 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -573,7 +573,7 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a++] = &(main->library); lb[a++] = &(main->wm); lb[a++] = &(main->movieclip); - lb[a++]= &(main->mask); + lb[a++] = &(main->mask); lb[a] = NULL; diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index a4361321442..3b93eab3192 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -169,7 +169,7 @@ int ED_operator_editmball(struct bContext *C); int ED_operator_uvedit(struct bContext *C); int ED_operator_uvmap(struct bContext *C); int ED_operator_posemode(struct bContext *C); -int ED_operator_mask(struct bContext *C); +int ED_operator_mask(struct bContext *C); /* default keymaps, bitflags */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index ba9c610a7e0..f915612b57a 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -95,7 +95,7 @@ enum { #define CTX_BMESH 64 #define CTX_NDOF 128 #define CTX_MOVIECLIP 256 -#define CTX_MASK 512 +#define CTX_MASK 512 /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index d898a1c5232..68494af684e 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -38,7 +38,7 @@ #include "BKE_mask.h" #include "DNA_mask_types.h" -#include "DNA_object_types.h" /* SELECT */ +#include "DNA_object_types.h" /* SELECT */ #include "ED_mask.h" @@ -47,7 +47,7 @@ #include "UI_resources.h" -#include "mask_intern.h" // own include +#include "mask_intern.h" /* own include */ typedef struct PixelSpaceContext { int width, height; @@ -102,11 +102,13 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceC glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); - } else + } + else { glColor3f(0.5f, 0.5f, 0.0f); + } glBegin(GL_POINTS); - glVertex2fv(fp); + glVertex2fv(fp); glEnd(); fp += 2; @@ -119,7 +121,7 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceC MaskSplinePoint *point = &spline->points[i]; BezTriple *bezt = &point->bezt; float vert[2], handle[2]; - int has_handle = BKE_mask_point_has_handle(point);; + int has_handle = BKE_mask_point_has_handle(point); copy_v2_v2(vert, bezt->vec[1]); BKE_mask_point_handle(point, pixelspace->aspx, pixelspace->aspy, handle); @@ -129,8 +131,8 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceC set_spline_color(shape, spline); glBegin(GL_LINES); - glVertex3fv(vert); - glVertex3fv(handle); + glVertex3fv(vert); + glVertex3fv(handle); glEnd(); } @@ -140,11 +142,12 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceC glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); - } else + } + else glColor3f(0.5f, 0.5f, 0.0f); glBegin(GL_POINTS); - glVertex3fv(vert); + glVertex3fv(vert); glEnd(); /* draw handle points */ @@ -154,11 +157,13 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceC glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); - } else + } + else { glColor3f(0.5f, 0.5f, 0.0f); + } glBegin(GL_POINTS); - glVertex3fv(handle); + glVertex3fv(handle); glEnd(); } } @@ -176,7 +181,8 @@ static void draw_spline_curve_lines(float *points, int tot_point, int closed) else glBegin(GL_LINE_STRIP); - for (i = 0; i < tot_point; i++, fp+=2) { + /* MASK_TODO - vertex arrays */ + for (i = 0; i < tot_point; i++, fp += 2) { glVertex3fv(fp); } glEnd(); @@ -210,7 +216,7 @@ static void draw_spline_curve(MaskShape *shape, MaskSpline *spline, PixelSpaceCo return; feather_points = BKE_mask_spline_feather_differentiated_points(spline, pixelspace->aspx, pixelspace->aspy, - &tot_feather_point); + &tot_feather_point); /* draw feather */ if (spline->flag & SELECT) diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index 2325820880b..633f75c643b 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -47,7 +47,7 @@ #include "RNA_access.h" -#include "mask_intern.h" // own include +#include "mask_intern.h" /* own include */ /********************** generic poll functions *********************/ @@ -204,13 +204,13 @@ void ED_operatormacros_mask(void) wmOperatorType *ot; wmOperatorTypeMacro *otmacro; - ot= WM_operatortype_append_macro("MASK_OT_add_vertex_slide", "Add Vertex and Slide", "Add new vertex and slide it", OPTYPE_UNDO|OPTYPE_REGISTER); + ot = WM_operatortype_append_macro("MASK_OT_add_vertex_slide", "Add Vertex and Slide", "Add new vertex and slide it", OPTYPE_UNDO | OPTYPE_REGISTER); ot->description = "Add new vertex and slide it"; WM_operatortype_macro_define(ot, "MASK_OT_add_vertex"); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_boolean_set(otmacro->ptr, "release_confirm", TRUE); - ot= WM_operatortype_append_macro("MASK_OT_add_feather_vertex_slide", "Add Feather Vertex and Slide", "Add new vertex to feater and slide it", OPTYPE_UNDO|OPTYPE_REGISTER); + ot = WM_operatortype_append_macro("MASK_OT_add_feather_vertex_slide", "Add Feather Vertex and Slide", "Add new vertex to feater and slide it", OPTYPE_UNDO | OPTYPE_REGISTER); ot->description = "Add new feather vertex and slide it"; WM_operatortype_macro_define(ot, "MASK_OT_add_feather_vertex"); otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point"); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index acfd633a811..aee73205c99 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -41,7 +41,7 @@ #include "BKE_mask.h" #include "DNA_mask_types.h" -#include "DNA_object_types.h" /* SELECT */ +#include "DNA_object_types.h" /* SELECT */ #include "WM_api.h" #include "WM_types.h" @@ -53,7 +53,7 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "mask_intern.h" // own include +#include "mask_intern.h" /* own include */ /******************** utility functions *********************/ @@ -88,8 +88,11 @@ static void spline_point_select(MaskSplinePoint *point, int action) } } -static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, float aspx, float aspy, float start_u, float co[2]) + +static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, float aspx, float aspy, float start_u, const float co[2]) { + const float proj_eps = 1e-3; + const float proj_eps_squared = proj_eps * proj_eps; const int N = 1000; float u = -1.0f, du = 1.0f / N, u1 = start_u, u2 = start_u; float ang = -1.0f; @@ -104,7 +107,7 @@ static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, fl BKE_mask_point_normal(spline, point, aspx, aspy, u1, n1); sub_v2_v2v2(v1, co, co1); - if (len_v2(v1) > 1e-3) { + if (len_squared_v2(v1) > proj_eps_squared) { ang1 = angle_v2v2(v1, n1); if (ang1 > M_PI / 2.0f) ang1 = M_PI - ang1; @@ -125,7 +128,7 @@ static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, fl BKE_mask_point_normal(spline, point, aspx, aspy, u2, n2); sub_v2_v2v2(v2, co, co2); - if (len_v2(v2) > 1e-3) { + if (len_squared_v2(v2) > proj_eps_squared) { ang2 = angle_v2v2(v2, n2); if (ang2 > M_PI / 2.0f) ang2 = M_PI - ang2; @@ -441,7 +444,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], if (feather) { feather_points = BKE_mask_point_segment_feather_diff(spline, cur_point, - aspx, aspy, &tot_feather_point); + aspx, aspy, &tot_feather_point); points = feather_points; tot_point = tot_feather_point; @@ -563,7 +566,7 @@ static int mask_new_exec(bContext *C, wmOperator *op) { SpaceClip *sc = CTX_wm_space_clip(C); Mask *mask; - char name[MAX_ID_NAME-2]; + char name[MAX_ID_NAME - 2]; RNA_string_get(op->ptr, "name", name); @@ -583,14 +586,14 @@ void MASK_OT_new(wmOperatorType *ot) ot->idname = "MASK_OT_new"; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* api callbacks */ ot->exec = mask_new_exec; ot->poll = ED_operator_mask; /* properties */ - RNA_def_string(ot->srna, "name", "", MAX_ID_NAME-2, "Name", "Name of new mask"); + RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask"); } /******************** create new shape *********************/ @@ -598,14 +601,14 @@ void MASK_OT_new(wmOperatorType *ot) static int shape_new_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - char name[MAX_ID_NAME-2]; + char name[MAX_ID_NAME - 2]; RNA_string_get(op->ptr, "name", name); BKE_mask_shape_new(mask, name); mask->shapenr = mask->tot_shape - 1; - WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; } @@ -622,10 +625,10 @@ void MASK_OT_shape_new(wmOperatorType *ot) ot->poll = ED_maskediting_poll; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_string(ot->srna, "name", "", MAX_ID_NAME-2, "Name", "Name of new shape"); + RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new shape"); } /******************** remove shape *********************/ @@ -638,7 +641,7 @@ static int shape_remove_exec(bContext *C, wmOperator *UNUSED(op)) if (shape) { BKE_mask_shape_remove(mask, shape); - WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); } return OPERATOR_FINISHED; @@ -656,15 +659,15 @@ void MASK_OT_shape_remove(wmOperatorType *ot) ot->poll = ED_maskediting_poll; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /******************** slide *********************/ -#define SLIDE_ACTION_NONE 0 -#define SLIDE_ACTION_POINT 1 -#define SLIDE_ACTION_HANDLE 2 -#define SLIDE_ACTION_FEATHER 3 +#define SLIDE_ACTION_NONE 0 +#define SLIDE_ACTION_POINT 1 +#define SLIDE_ACTION_HANDLE 2 +#define SLIDE_ACTION_FEATHER 3 typedef struct SlidePointData { int action; @@ -798,7 +801,7 @@ static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) slidedata->shape->act_spline = slidedata->spline; slidedata->shape->act_point = slidedata->point; - WM_event_add_notifier(C, NC_MASK|ND_SELECT, mask); + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_RUNNING_MODAL; } @@ -831,18 +834,18 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) BezTriple *bezt = &data->point->bezt; float co[2], dco[2]; - switch(event->type) { + switch (event->type) { case LEFTCTRLKEY: case RIGHTCTRLKEY: case LEFTSHIFTKEY: case RIGHTSHIFTKEY: if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) - data->curvature_only = event->val==KM_PRESS; + data->curvature_only = event->val == KM_PRESS; if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) - data->accurate = event->val==KM_PRESS; + data->accurate = event->val == KM_PRESS; - /* no break! update CV position */ + /* no break! update CV position */ case MOUSEMOVE: ED_mask_mouse_pos(C, event, co); @@ -909,16 +912,16 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) *weight = 0; } - WM_event_add_notifier(C, NC_MASK|NA_EDITED, data->mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); DAG_id_tag_update(&data->mask->id, 0); break; case LEFTMOUSE: - if(event->val==KM_RELEASE) { + if (event->val == KM_RELEASE) { free_slide_point_data(op->customdata); - WM_event_add_notifier(C, NC_MASK|NA_EDITED, data->mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); DAG_id_tag_update(&data->mask->id, 0); return OPERATOR_FINISHED; @@ -931,7 +934,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) free_slide_point_data(op->customdata); - WM_event_add_notifier(C, NC_MASK|NA_EDITED, data->mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); DAG_id_tag_update(&data->mask->id, 0); return OPERATOR_CANCELLED; @@ -953,7 +956,7 @@ void MASK_OT_slide_point(wmOperatorType *ot) ot->poll = ED_maskediting_mask_poll; /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide slide feather instead of vertex"); } @@ -968,7 +971,7 @@ static int select_all_exec(bContext *C, wmOperator *op) toggle_selection_all(mask, action); mask_flush_selection(mask); - WM_event_add_notifier(C, NC_MASK|ND_SELECT, mask); + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; } @@ -985,7 +988,7 @@ void MASK_OT_select_all(wmOperatorType *ot) ot->poll = ED_maskediting_mask_poll; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ WM_operator_properties_select_all(ot); @@ -1024,7 +1027,7 @@ static int select_exec(bContext *C, wmOperator *op) mask_flush_selection(mask); - WM_event_add_notifier(C, NC_MASK|ND_SELECT, mask); + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); } else { MaskSplinePointUW *uw; @@ -1040,7 +1043,7 @@ static int select_exec(bContext *C, wmOperator *op) mask_flush_selection(mask); - WM_event_add_notifier(C, NC_MASK|ND_SELECT, mask); + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); } } @@ -1075,9 +1078,9 @@ void MASK_OT_select(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "extend", 0, - "Extend", "Extend selection rather than clearing the existing selection"); + "Extend", "Extend selection rather than clearing the existing selection"); RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, - "Location", "Location of vertex in normalized space", -1.0f, 1.0f); + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); } /******************** add vertex *********************/ @@ -1125,7 +1128,8 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask sub_v2_v2(bezt->vec[0], vec); add_v2_v2(bezt->vec[2], vec); - } else { + } + else { /* next points are aligning in the direction of previous/next point */ MaskSplinePoint *point; float v1[2], v2[2], vec[2]; @@ -1134,7 +1138,8 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask if (new_point == spline->points) { point = new_point + 1; dir = -1.0f; - } else + } + else point = new_point - 1; if (spline->tot_point < 3) { @@ -1210,7 +1215,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) shape->act_point = new_point; - WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return TRUE; } @@ -1312,7 +1317,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) shape->act_point = new_point; setup_vertex_point(C, mask, spline, new_point, co, NULL); - WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return TRUE; } @@ -1356,11 +1361,11 @@ void MASK_OT_add_vertex(wmOperatorType *ot) ot->poll = ED_maskediting_mask_poll; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, - "Location", "Location of vertex in normalized space", -1.0f, 1.0f); + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); } /******************** add feather vertex *********************/ @@ -1385,7 +1390,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) BKE_mask_point_add_uw(point, u, w); - WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; } @@ -1417,11 +1422,11 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot) ot->poll = ED_maskediting_mask_poll; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, - "Location", "Location of vertex in normalized space", -1.0f, 1.0f); + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); } /******************** toggle cyclic *********************/ @@ -1444,7 +1449,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) shape = shape->next; } - WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; } @@ -1461,7 +1466,7 @@ void MASK_OT_cyclic_toggle(wmOperatorType *ot) ot->poll = ED_maskediting_mask_poll; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /******************** delete *********************/ @@ -1536,7 +1541,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) MaskSplinePoint *new_points; int j; - new_points = MEM_callocN(count*sizeof(MaskSplinePoint), "deleteMaskPoints"); + new_points = MEM_callocN(count * sizeof(MaskSplinePoint), "deleteMaskPoints"); for (i = 0, j = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; @@ -1571,7 +1576,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) shape = shape->next; } - WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; } @@ -1589,7 +1594,7 @@ void MASK_OT_delete(wmOperatorType *ot) ot->poll = ED_maskediting_mask_poll; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /******************** set handle type *********************/ @@ -1621,7 +1626,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) shape = shape->next; } - WM_event_add_notifier(C, NC_MASK|ND_DATA, mask); + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; @@ -1629,11 +1634,12 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) void MASK_OT_handle_type_set(wmOperatorType *ot) { - static EnumPropertyItem editcurve_handle_type_items[]= { + static EnumPropertyItem editcurve_handle_type_items[] = { {HD_AUTO, "AUTO", 0, "Auto", ""}, {HD_VECT, "VECTOR", 0, "Vector", ""}, {HD_ALIGN, "ALIGNED", 0, "Aligned", ""}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL} + }; /* identifiers */ ot->name = "Set Handle Type"; @@ -1646,7 +1652,7 @@ void MASK_OT_handle_type_set(wmOperatorType *ot) ot->poll = ED_maskediting_mask_poll; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type"); From cf6450256db6eaf0ea37d4c64f648d22d8954099 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 13 May 2012 21:46:18 +0000 Subject: [PATCH 034/183] style cleanup: comments and whitespace --- intern/raskter/raskter.c | 251 ++++++++++++++++++++------------------- 1 file changed, 127 insertions(+), 124 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index afa8b2102ae..b80b7de379b 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -31,7 +31,7 @@ #include #include "raskter.h" -// from BLI_utildefines.h +/* from BLI_utildefines.h */ #define MIN2(x, y) ( (x) < (y) ? (x) : (y) ) #define MAX2(x, y) ( (x) > (y) ? (x) : (y) ) @@ -64,7 +64,8 @@ static struct r_buffer_stats rb; * just the poly. Since the DEM code could end up being coupled with this, we'll keep it separate * for now. */ -static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct e_status *open_edge) { +static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct e_status *open_edge) +{ int i; int xbeg; int ybeg; @@ -78,44 +79,44 @@ static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct struct e_status *next_edge; struct e_status **next_edge_ref; struct poly_vert *v; - // set up pointers + /* set up pointers */ v = verts; all_edges = NULL; - // loop all verts + /* loop all verts */ for (i = 0; i < num_verts; i++) { - // determine beginnings and endings of edges, linking last vertex to first vertex + /* determine beginnings and endings of edges, linking last vertex to first vertex */ xbeg = v[i].x; ybeg = v[i].y; if (i) { - // we're not at the last vert, so end of the edge is the previous vertex + /* we're not at the last vert, so end of the edge is the previous vertex */ xend = v[i - 1].x; yend = v[i - 1].y; } else { - // we're at the first vertex, so the "end" of this edge is the last vertex + /* we're at the first vertex, so the "end" of this edge is the last vertex */ xend = v[num_verts - 1].x; yend = v[num_verts - 1].y; } - // make sure our edges are facing the correct direction + /* make sure our edges are facing the correct direction */ if (ybeg > yend) { - // flip the Xs + /* flip the Xs */ temp_pos = xbeg; xbeg = xend; xend = temp_pos; - // flip the Ys + /* flip the Ys */ temp_pos = ybeg; ybeg = yend; yend = temp_pos; } - // calculate y delta + /* calculate y delta */ dy = yend - ybeg; - // dont draw horizontal lines directly, they are scanned as part of the edges they connect, so skip em. :) + /* dont draw horizontal lines directly, they are scanned as part of the edges they connect, so skip em. :) */ if (dy) { - // create the edge and determine it's slope (for incremental line drawing) + /* create the edge and determine it's slope (for incremental line drawing) */ e_new = open_edge++; - // calculate x delta + /* calculate x delta */ dx = xend - xbeg; if (dx > 0) { e_new->xdir = 1; @@ -131,7 +132,7 @@ static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct e_new->num = dy; e_new->drift_dec = dy; - // calculate deltas for incremental drawing + /* calculate deltas for incremental drawing */ if (dx >= 0) { e_new->drift = 0; } @@ -147,7 +148,7 @@ static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct e_new->xshift = (xdist / dy) * e_new->xdir; } next_edge_ref = &all_edges; - // link in all the edges, in sorted order + /* link in all the edges, in sorted order */ for (;; ) { next_edge = *next_edge_ref; if (!next_edge || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) { @@ -166,150 +167,152 @@ static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need * if it ends up being coupled with this function. */ -int rast_scan_fill(struct poly_vert *verts, int num_verts) { - int x_curr; // current pixel position in X - int y_curr; // current scan line being drawn - int yp; // y-pixel's position in frame buffer - int swixd = 0; // whether or not edges switched position in X - float *cpxl; // pixel pointers... +int rast_scan_fill(struct poly_vert *verts, int num_verts) +{ + int x_curr; /* current pixel position in X */ + int y_curr; /* current scan line being drawn */ + int yp; /* y-pixel's position in frame buffer */ + int swixd = 0; /* whether or not edges switched position in X */ + float *cpxl; /* pixel pointers... */ float *mpxl; float *spxl; - struct e_status *e_curr; // edge pointers... + struct e_status *e_curr; /* edge pointers... */ struct e_status *e_temp; struct e_status *edgbuf; struct e_status **edgec; /* - If the number of verts specified to render as a polygon is less than 3, - return immediately. Obviously we cant render a poly with sides < 3. The - return for this we set to 1, simply so it can be distinguished from the - next place we could return, which is a failure to allocate memory. + * If the number of verts specified to render as a polygon is less than 3, + * return immediately. Obviously we cant render a poly with sides < 3. The + * return for this we set to 1, simply so it can be distinguished from the + * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter.cwhich is a failure to allocate memory. */ if (num_verts < 3) { return(1); } /* - Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data - multiplied by the number of edges, which is always equal to the number of verts in - a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for - the preceeding error, which was a rasterization request on a 2D poly with less than - 3 sides. + * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data + * multiplied by the number of edges, which is always equal to the number of verts in + * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for + * the preceeding error, which was a rasterization request on a 2D poly with less than + * 3 sides. */ if ((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_verts))) == NULL) { return(0); } /* - Do some preprocessing on all edges. This constructs a table structure in memory of all - the edge properties and can "flip" some edges so sorting works correctly. + * Do some preprocessing on all edges. This constructs a table structure in memory of all + * the edge properties and can "flip" some edges so sorting works correctly. */ preprocess_all_edges(verts, num_verts, edgbuf); /* - Set the pointer for tracking the edges currently in processing to NULL to make sure - we don't get some crazy value after initialization. + * Set the pointer for tracking the edges currently in processing to NULL to make sure + * we don't get some crazy value after initialization. */ possible_edges = NULL; /* - Loop through all scan lines to be drawn. Since we sorted by Y values during - preprocess_all_edges(), we can already exact values for the lowest and - highest Y values we could possibly need by induction. The preprocessing sorted - out edges by Y position, we can cycle the current edge being processed once - it runs out of Y pixels. When we have no more edges, meaning the current edge - is NULL after setting the "current" edge to be the previous current edge's - "next" edge in the Y sorted edge connection chain, we can stop looping Y values, - since we can't possibly have more scan lines if we ran out of edges. :) - - TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. - Will get changed once DEM code gets in. + * Loop through all scan lines to be drawn. Since we sorted by Y values during + * preprocess_all_edges(), we can already exact values for the lowest and + * highest Y values we could possibly need by induction. The preprocessing sorted + * out edges by Y position, we can cycle the current edge being processed once + * it runs out of Y pixels. When we have no more edges, meaning the current edge + * is NULL after setting the "current" edge to be the previous current edge's + * "next" edge in the Y sorted edge connection chain, we can stop looping Y values, + * since we can't possibly have more scan lines if we ran out of edges. :) + * + * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. + * Will get changed once DEM code gets in. */ for (y_curr = MAX2(all_edges->ybeg, 0); (all_edges || possible_edges) && (y_curr < rb.sizey); y_curr++) { /* - Link any edges that start on the current scan line into the list of - edges currently needed to draw at least this, if not several, scan lines. + * Link any edges that start on the current scan line into the list of + * edges currently needed to draw at least this, if not several, scan lines. */ /* - Set the current edge to the beginning of the list of edges to be rasterized - into this scan line. - - We could have lots of edge here, so iterate over all the edges needed. The - preprocess_all_edges() function sorted edges by X within each chunk of Y sorting - so we safely cycle edges to thier own "next" edges in order. - - At each iteration, make sure we still have a non-NULL edge. + * Set the current edge to the beginning of the list of edges to be rasterized + * into this scan line. + * + * We could have lots of edge here, so iterate over all the edges needed. The + * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting + * so we safely cycle edges to thier own "next" edges in order. + * + * At each iteration, make sure we still have a non-NULL edge. */ for (edgec = &possible_edges; all_edges && (all_edges->ybeg == y_curr); ) { - x_curr = all_edges->x; // Set current X position. - for (;; ) { // Start looping edges. Will break when edges run out. - e_curr = *edgec; // Set up a current edge pointer. - if (!e_curr || (e_curr->x >= x_curr)) { // If we have an no edge, or we need to skip some X-span, - e_temp = all_edges->e_next; // set a temp "next" edge to test. - *edgec = all_edges; // Add this edge to the list to be scanned. - all_edges->e_next = e_curr; // Set up the next edge. - edgec = &all_edges->e_next; // Set our list to the next edge's location in memory. - all_edges = e_temp; // Skip the NULL or bad X edge, set pointer to next edge. - break; // Stop looping edges (since we ran out or hit empty X span. + x_curr = all_edges->x; /* Set current X position. */ + for (;; ) { /* Start looping edges. Will break when edges run out. */ + e_curr = *edgec; /* Set up a current edge pointer. */ + if (!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ + e_temp = all_edges->e_next; /* set a temp "next" edge to test. */ + *edgec = all_edges; /* Add this edge to the list to be scanned. */ + all_edges->e_next = e_curr; /* Set up the next edge. */ + edgec = &all_edges->e_next; /* Set our list to the next edge's location in memory. */ + all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ + break; /* Stop looping edges (since we ran out or hit empty X span. */ } else { - edgec = &e_curr->e_next; // Set the pointer to the edge list the "next" edge. + edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ } } } /* - Determine the current scan line's offset in the pixel buffer based on its Y position. - Basically we just multiply the current scan line's Y value by the number of pixels in each line. + * Determine the current scan line's offset in the pixel buffer based on its Y position. + * Basically we just multiply the current scan line's Y value by the number of pixels in each line. */ yp = y_curr * rb.sizex; /* - Set a "scan line pointer" in memory. The location of the buffer plus the row offset. + * Set a "scan line pointer" in memory. The location of the buffer plus the row offset. */ spxl = rb.buf + (yp); /* - Set up the current edge to the first (in X) edge. The edges which could possibly be in this - list were determined in the preceeding edge loop above. They were already sorted in X by the - initial processing function. - - At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge - we will eventually hit a NULL when the list runs out. + * Set up the current edge to the first (in X) edge. The edges which could possibly be in this + * list were determined in the preceeding edge loop above. They were already sorted in X by the + * initial processing function. + * + * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge + * we will eventually hit a NULL when the list runs out. */ for (e_curr = possible_edges; e_curr; e_curr = e_curr->e_next) { /* - Calculate a span of pixels to fill on the current scan line. - - Set the current pixel pointer by adding the X offset to the scan line's start offset. - Cycle the current edge the next edge. - Set the max X value to draw to be one less than the next edge's first pixel. This way we are - sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than - one time because it's on a vertex connecting two edges) - - Then blast through all the pixels in the span, advancing the pointer and setting the color to white. - - TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, - but for now it is done here until the DEM code comes in. + * Calculate a span of pixels to fill on the current scan line. + * + * Set the current pixel pointer by adding the X offset to the scan line's start offset. + * Cycle the current edge the next edge. + * Set the max X value to draw to be one less than the next edge's first pixel. This way we are + * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than + * one time because it's on a vertex connecting two edges) + * + * Then blast through all the pixels in the span, advancing the pointer and setting the color to white. + * + * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, + * but for now it is done here until the DEM code comes in. */ - // set up xmin and xmax bounds on this scan line + + /* set up xmin and xmax bounds on this scan line */ cpxl = spxl + MAX2(e_curr->x, 0); e_curr = e_curr->e_next; mpxl = spxl + MIN2(e_curr->x, rb.sizex) - 1; - // draw the pixels. + /* draw the pixels. */ for (; cpxl <= mpxl; *cpxl++ = 1.0f) ; } /* - Loop through all edges of polygon that could be hit by this scan line, - and figure out their x-intersections with the next scan line. - - Either A.) we wont have any more edges to test, or B.) we just add on the - slope delta computed in preprocessing step. Since this draws non-antialiased - polygons, we dont have fractional positions, so we only move in x-direction - when needed to get all the way to the next pixel over... + * Loop through all edges of polygon that could be hit by this scan line, + * and figure out their x-intersections with the next scan line. + * + * Either A.) we wont have any more edges to test, or B.) we just add on the + * slope delta computed in preprocessing step. Since this draws non-antialiased + * polygons, we dont have fractional positions, so we only move in x-direction + * when needed to get all the way to the next pixel over... */ for (edgec = &possible_edges; (e_curr = *edgec); ) { if (!(--(e_curr->num))) { @@ -325,43 +328,43 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) { } } /* - It's possible that some edges may have crossed during the last step, so we'll be sure - that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges - sorted by x-intersection coordinate. We'll always scan through at least once to see if - edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial - pass, then we know we need to sort by x, so then cycle through edges again and perform - the sort.- + * It's possible that some edges may have crossed during the last step, so we'll be sure + * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges + * sorted by x-intersection coordinate. We'll always scan through at least once to see if + * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial + * pass, then we know we need to sort by x, so then cycle through edges again and perform + * the sort.- */ if (possible_edges) { for (edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - // if the current edge hits scan line at greater X than the next edge, we need to exchange the edges + /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ if (e_curr->x > e_curr->e_next->x) { *edgec = e_curr->e_next; - // exchange the pointers + /* exchange the pointers */ e_temp = e_curr->e_next->e_next; e_curr->e_next->e_next = e_curr; e_curr->e_next = e_temp; - // set flag that we had at least one switch + /* set flag that we had at least one switch */ swixd = 1; } } - // if we did have a switch, look for more (there will more if there was one) + /* if we did have a switch, look for more (there will more if there was one) */ for (;; ) { - // reset exchange flag so it's only set if we encounter another one + /* reset exchange flag so it's only set if we encounter another one */ swixd = 0; for (edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - // again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag + /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */ if (e_curr->x > e_curr->e_next->x) { *edgec = e_curr->e_next; - // exchange the pointers + /* exchange the pointers */ e_temp = e_curr->e_next->e_next; e_curr->e_next->e_next = e_curr; e_curr->e_next = e_temp; - // flip the exchanged flag + /* flip the exchanged flag */ swixd = 1; } } - // if we had no exchanges, we're done reshuffling the pointers + /* if we had no exchanges, we're done reshuffling the pointers */ if (!swixd) { break; } @@ -374,8 +377,8 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) { } int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { - int i; // i: Loop counter. - struct poly_vert *ply; // ply: Pointer to a list of integer buffer-space vertex coordinates. + int i; /* i: Loop counter. */ + struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ /* * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert @@ -396,17 +399,17 @@ int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel * drawn will be 1.0f in value, there is no anti-aliasing. */ - for (i = 0; i < num; i++) { // Loop over all verts. - ply[i].x = (verts[i << 1] * buf_x) + 0.5f; // Range expand normalized X to integer buffer-space X. - ply[i].y = (verts[(i << 1) + 1] * buf_y) + 0.5f; // Range expand normalized Y to integer buffer-space Y. + for (i = 0; i < num; i++) { /* Loop over all verts. */ + ply[i].x = (verts[i << 1] * buf_x) + 0.5f; /* Range expand normalized X to integer buffer-space X. */ + ply[i].y = (verts[(i << 1) + 1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */ } - rb.buf = buf; // Set the output buffer pointer. - rb.sizex = buf_x; // Set the output buffer size in X. (width) - rb.sizey = buf_y; // Set the output buffer size in Y. (height) + rb.buf = buf; /* Set the output buffer pointer. */ + rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ + rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ - i = rast_scan_fill(ply, num); // Call our rasterizer, passing in the integer coords for each vert. - free(ply); // Free the memory allocated for the integer coordinate table. - return(i); // Return the value returned by the rasterizer. + i = rast_scan_fill(ply, num); /* Call our rasterizer, passing in the integer coords for each vert. */ + free(ply); /* Free the memory allocated for the integer coordinate table. */ + return(i); /* Return the value returned by the rasterizer. */ } From bac340e6740ea4f5f1ac41a47b6a540d726c4ac6 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Sun, 13 May 2012 23:08:56 +0000 Subject: [PATCH 035/183] Add a planar tracking implementation to libmv This adds a new planar tracking implementation to libmv. The tracker is based on Ceres[1], the new nonlinear minimizer that myself and Sameer released from Google as open source. Since the motion model is more involved, the interface is different than the RegionTracker interface used previously in Blender. The start of a C API in libmv-capi.{cpp,h} is also included. The ESM tracker, also known as the KLT tracker in the UI, is temporarily changed to use the new Ceres-based planar tracker in translation-only mode. Currently it is a bit slower than ESM and also doesn't have all the bells and whistles implemented. Those will come soon. Longer term, both trackers will remain since Ceres is unlikely to be as fast as ESM for pure translation solving, due to its generality. The next step is to implement a new tracking UI. The current UI assumes a translational motion model; the new one must support arbitrary perspective transforms of the pattern regions. [1] http://code.google.com/p/ceres-solver --- extern/libmv/CMakeLists.txt | 2 + extern/libmv/libmv-capi.cpp | 68 +- extern/libmv/libmv-capi.h | 21 + extern/libmv/libmv/multiview/homography.cc | 267 +++++++ extern/libmv/libmv/multiview/homography.h | 84 +++ .../multiview/homography_parameterization.h | 91 +++ .../libmv/tracking/esm_region_tracker.cc | 40 ++ extern/libmv/libmv/tracking/track_region.cc | 651 ++++++++++++++++++ extern/libmv/libmv/tracking/track_region.h | 91 +++ 9 files changed, 1314 insertions(+), 1 deletion(-) create mode 100644 extern/libmv/libmv/multiview/homography.cc create mode 100644 extern/libmv/libmv/multiview/homography.h create mode 100644 extern/libmv/libmv/multiview/homography_parameterization.h create mode 100644 extern/libmv/libmv/tracking/track_region.cc create mode 100644 extern/libmv/libmv/tracking/track_region.h diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index cf0ad1102e0..60cd84d89d4 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -62,6 +62,7 @@ set(SRC libmv/multiview/fundamental.cc libmv/multiview/projection.cc libmv/multiview/triangulation.cc + libmv/multiview/homography.cc libmv/numeric/numeric.cc libmv/numeric/poly.cc libmv/simple_pipeline/bundle.cc @@ -84,6 +85,7 @@ set(SRC libmv/tracking/pyramid_region_tracker.cc libmv/tracking/retrack_region_tracker.cc libmv/tracking/trklt_region_tracker.cc + libmv/tracking/track_region.cc third_party/fast/fast_10.c third_party/fast/fast_11.c diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 6c20d76eeac..ddf69ce5e28 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -45,6 +45,7 @@ #include "libmv/tracking/trklt_region_tracker.h" #include "libmv/tracking/lmicklt_region_tracker.h" #include "libmv/tracking/pyramid_region_tracker.h" +#include "libmv/tracking/track_region.h" #include "libmv/simple_pipeline/callbacks.h" #include "libmv/simple_pipeline/tracks.h" @@ -97,7 +98,7 @@ void libmv_initLogging(const char *argv0) void libmv_startDebugLogging(void) { google::SetCommandLineOption("logtostderr", "1"); - google::SetCommandLineOption("v", "0"); + google::SetCommandLineOption("v", "2"); google::SetCommandLineOption("stderrthreshold", "1"); google::SetCommandLineOption("minloglevel", "0"); V3D::optimizerVerbosenessLevel = 1; @@ -329,6 +330,71 @@ void libmv_regionTrackerDestroy(libmv_RegionTracker *libmv_tracker) delete region_tracker; } +/* ************ Planar tracker ************ */ + +/* TrackRegion (new planar tracker) */ +int libmv_trackRegion(const struct libmv_trackRegionOptions *options, + const float *image1, const float *image2, + int width, int height, + const double *x1, const double *y1, + struct libmv_trackRegionResult *result, + double *x2, double *y2) { + double xx1[4], yy1[4]; + double xx2[4], yy2[4]; + + // Convert to doubles for the libmv api. + for (int i = 0; i < 4; ++i) { + xx1[i] = x1[i]; + yy1[i] = y1[i]; + xx2[i] = x2[i]; + yy2[i] = y2[i]; + } + + libmv::TrackRegionOptions track_region_options; + switch (options->motion_model) { +#define LIBMV_CONVERT(the_model) \ + case libmv::TrackRegionOptions::the_model: \ + track_region_options.mode = libmv::TrackRegionOptions::the_model; \ + break; + LIBMV_CONVERT(TRANSLATION) + LIBMV_CONVERT(TRANSLATION_ROTATION) + LIBMV_CONVERT(TRANSLATION_SCALE) + LIBMV_CONVERT(TRANSLATION_ROTATION_SCALE) + LIBMV_CONVERT(AFFINE) + LIBMV_CONVERT(HOMOGRAPHY) +#undef LIBMV_CONVERT + } + track_region_options.num_samples_x = options->num_samples_x; + track_region_options.num_samples_y = options->num_samples_y; + track_region_options.minimum_correlation = options->minimum_correlation; + track_region_options.max_iterations = options->num_iterations; + track_region_options.sigma = options->sigma; + + // Convert from raw float buffers to libmv's FloatImage. + libmv::FloatImage old_patch, new_patch; + floatBufToImage(image1, width, height, &old_patch); + floatBufToImage(image2, width, height, &new_patch); + + libmv::TrackRegionResult track_region_result; + libmv::TrackRegion(old_patch, new_patch, xx1, yy1, track_region_options, xx2, yy2, &track_region_result); + + // Convert to floats for the blender api. + for (int i = 0; i < 4; ++i) { + x2[i] = xx2[i]; + y2[i] = yy2[i]; + } + + // TODO(keir): Update the termination string with failure details. + if (track_region_result.termination == libmv::TrackRegionResult::PARAMETER_TOLERANCE || + track_region_result.termination == libmv::TrackRegionResult::FUNCTION_TOLERANCE || + track_region_result.termination == libmv::TrackRegionResult::GRADIENT_TOLERANCE || + track_region_result.termination == libmv::TrackRegionResult::NO_CONVERGENCE || + track_region_result.termination == libmv::TrackRegionResult::INSUFFICIENT_CORRELATION) { + return true; + } + return false; +} + /* ************ Tracks ************ */ libmv_Tracks *libmv_tracksNew(void) diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index bccc4706832..d7d132d4f21 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -50,6 +50,27 @@ int libmv_regionTrackerTrack(struct libmv_RegionTracker *libmv_tracker, const fl int width, int height, double x1, double y1, double *x2, double *y2); void libmv_regionTrackerDestroy(struct libmv_RegionTracker *libmv_tracker); +/* TrackRegion (new planar tracker) */ +struct libmv_trackRegionOptions { + int motion_model; + int num_samples_x; + int num_samples_y; + int num_iterations; + double minimum_correlation; + double sigma; +}; +struct libmv_trackRegionResult { + int termination; + const char *termination_reason; + double correlation; +}; +int libmv_trackRegion(const struct libmv_trackRegionOptions *options, + const float *image1, const float *image2, + int width, int height, + const double *x1, const double *y1, + struct libmv_trackRegionResult *result, + double *x2, double *y2); + /* Tracks */ struct libmv_Tracks *libmv_tracksNew(void); void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track, double x, double y); diff --git a/extern/libmv/libmv/multiview/homography.cc b/extern/libmv/libmv/multiview/homography.cc new file mode 100644 index 00000000000..366392f3923 --- /dev/null +++ b/extern/libmv/libmv/multiview/homography.cc @@ -0,0 +1,267 @@ +// Copyright (c) 2008, 2009 libmv authors. +// +// 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. + +#include "libmv/logging/logging.h" +#include "libmv/multiview/homography.h" +#include "libmv/multiview/homography_parameterization.h" + +namespace libmv { +/** 2D Homography transformation estimation in the case that points are in + * euclidean coordinates. + * + * x = H y + * x and y vector must have the same direction, we could write + * crossproduct(|x|, * H * |y| ) = |0| + * + * | 0 -1 x2| |a b c| |y1| |0| + * | 1 0 -x1| * |d e f| * |y2| = |0| + * |-x2 x1 0| |g h 1| |1 | |0| + * + * That gives : + * + * (-d+x2*g)*y1 + (-e+x2*h)*y2 + -f+x2 |0| + * (a-x1*g)*y1 + (b-x1*h)*y2 + c-x1 = |0| + * (-x2*a+x1*d)*y1 + (-x2*b+x1*e)*y2 + -x2*c+x1*f |0| + */ +bool Homography2DFromCorrespondencesLinearEuc( + const Mat &x1, + const Mat &x2, + Mat3 *H, + double expected_precision) { + assert(2 == x1.rows()); + assert(4 <= x1.cols()); + assert(x1.rows() == x2.rows()); + assert(x1.cols() == x2.cols()); + + int n = x1.cols(); + MatX8 L = Mat::Zero(n * 3, 8); + Mat b = Mat::Zero(n * 3, 1); + for (int i = 0; i < n; ++i) { + int j = 3 * i; + L(j, 0) = x1(0, i); // a + L(j, 1) = x1(1, i); // b + L(j, 2) = 1.0; // c + L(j, 6) = -x2(0, i) * x1(0, i); // g + L(j, 7) = -x2(0, i) * x1(1, i); // h + b(j, 0) = x2(0, i); // i + + ++j; + L(j, 3) = x1(0, i); // d + L(j, 4) = x1(1, i); // e + L(j, 5) = 1.0; // f + L(j, 6) = -x2(1, i) * x1(0, i); // g + L(j, 7) = -x2(1, i) * x1(1, i); // h + b(j, 0) = x2(1, i); // i + + // This ensures better stability + // TODO(julien) make a lite version without this 3rd set + ++j; + L(j, 0) = x2(1, i) * x1(0, i); // a + L(j, 1) = x2(1, i) * x1(1, i); // b + L(j, 2) = x2(1, i); // c + L(j, 3) = -x2(0, i) * x1(0, i); // d + L(j, 4) = -x2(0, i) * x1(1, i); // e + L(j, 5) = -x2(0, i) ; // f + } + // Solve Lx=B + Vec h = L.fullPivLu().solve(b); + Homography2DNormalizedParameterization::To(h, H); + if ((L * h).isApprox(b, expected_precision)) { + return true; + } else { + return false; + } +} + +/** 2D Homography transformation estimation in the case that points are in + * homogeneous coordinates. + * + * | 0 -x3 x2| |a b c| |y1| -x3*d+x2*g -x3*e+x2*h -x3*f+x2*1 |y1| (-x3*d+x2*g)*y1 (-x3*e+x2*h)*y2 (-x3*f+x2*1)*y3 |0| + * | x3 0 -x1| * |d e f| * |y2| = x3*a-x1*g x3*b-x1*h x3*c-x1*1 * |y2| = (x3*a-x1*g)*y1 (x3*b-x1*h)*y2 (x3*c-x1*1)*y3 = |0| + * |-x2 x1 0| |g h 1| |y3| -x2*a+x1*d -x2*b+x1*e -x2*c+x1*f |y3| (-x2*a+x1*d)*y1 (-x2*b+x1*e)*y2 (-x2*c+x1*f)*y3 |0| + * X = |a b c d e f g h|^t + */ +bool Homography2DFromCorrespondencesLinear(const Mat &x1, + const Mat &x2, + Mat3 *H, + double expected_precision) { + if (x1.rows() == 2) { + return Homography2DFromCorrespondencesLinearEuc(x1, x2, H, + expected_precision); + } + assert(3 == x1.rows()); + assert(4 <= x1.cols()); + assert(x1.rows() == x2.rows()); + assert(x1.cols() == x2.cols()); + + const int x = 0; + const int y = 1; + const int w = 2; + int n = x1.cols(); + MatX8 L = Mat::Zero(n * 3, 8); + Mat b = Mat::Zero(n * 3, 1); + for (int i = 0; i < n; ++i) { + int j = 3 * i; + L(j, 0) = x2(w, i) * x1(x, i);//a + L(j, 1) = x2(w, i) * x1(y, i);//b + L(j, 2) = x2(w, i) * x1(w, i);//c + L(j, 6) = -x2(x, i) * x1(x, i);//g + L(j, 7) = -x2(x, i) * x1(y, i);//h + b(j, 0) = x2(x, i) * x1(w, i); + + ++j; + L(j, 3) = x2(w, i) * x1(x, i);//d + L(j, 4) = x2(w, i) * x1(y, i);//e + L(j, 5) = x2(w, i) * x1(w, i);//f + L(j, 6) = -x2(y, i) * x1(x, i);//g + L(j, 7) = -x2(y, i) * x1(y, i);//h + b(j, 0) = x2(y, i) * x1(w, i); + + // This ensures better stability + ++j; + L(j, 0) = x2(y, i) * x1(x, i);//a + L(j, 1) = x2(y, i) * x1(y, i);//b + L(j, 2) = x2(y, i) * x1(w, i);//c + L(j, 3) = -x2(x, i) * x1(x, i);//d + L(j, 4) = -x2(x, i) * x1(y, i);//e + L(j, 5) = -x2(x, i) * x1(w, i);//f + } + // Solve Lx=B + Vec h = L.fullPivLu().solve(b); + if ((L * h).isApprox(b, expected_precision)) { + Homography2DNormalizedParameterization::To(h, H); + return true; + } else { + return false; + } +} +/** + * x2 ~ A * x1 + * x2^t * Hi * A *x1 = 0 + * H1 = H2 = H3 = + * | 0 0 0 1| |-x2w| |0 0 0 0| | 0 | | 0 0 1 0| |-x2z| + * | 0 0 0 0| -> | 0 | |0 0 1 0| -> |-x2z| | 0 0 0 0| -> | 0 | + * | 0 0 0 0| | 0 | |0-1 0 0| | x2y| |-1 0 0 0| | x2x| + * |-1 0 0 0| | x2x| |0 0 0 0| | 0 | | 0 0 0 0| | 0 | + * H4 = H5 = H6 = + * |0 0 0 0| | 0 | | 0 1 0 0| |-x2y| |0 0 0 0| | 0 | + * |0 0 0 1| -> |-x2w| |-1 0 0 0| -> | x2x| |0 0 0 0| -> | 0 | + * |0 0 0 0| | 0 | | 0 0 0 0| | 0 | |0 0 0 1| |-x2w| + * |0-1 0 0| | x2y| | 0 0 0 0| | 0 | |0 0-1 0| | x2z| + * |a b c d| + * A = |e f g h| + * |i j k l| + * |m n o 1| + * + * x2^t * H1 * A *x1 = (-x2w*a +x2x*m )*x1x + (-x2w*b +x2x*n )*x1y + (-x2w*c +x2x*o )*x1z + (-x2w*d +x2x*1 )*x1w = 0 + * x2^t * H2 * A *x1 = (-x2z*e +x2y*i )*x1x + (-x2z*f +x2y*j )*x1y + (-x2z*g +x2y*k )*x1z + (-x2z*h +x2y*l )*x1w = 0 + * x2^t * H3 * A *x1 = (-x2z*a +x2x*i )*x1x + (-x2z*b +x2x*j )*x1y + (-x2z*c +x2x*k )*x1z + (-x2z*d +x2x*l )*x1w = 0 + * x2^t * H4 * A *x1 = (-x2w*e +x2y*m )*x1x + (-x2w*f +x2y*n )*x1y + (-x2w*g +x2y*o )*x1z + (-x2w*h +x2y*1 )*x1w = 0 + * x2^t * H5 * A *x1 = (-x2y*a +x2x*e )*x1x + (-x2y*b +x2x*f )*x1y + (-x2y*c +x2x*g )*x1z + (-x2y*d +x2x*h )*x1w = 0 + * x2^t * H6 * A *x1 = (-x2w*i +x2z*m )*x1x + (-x2w*j +x2z*n )*x1y + (-x2w*k +x2z*o )*x1z + (-x2w*l +x2z*1 )*x1w = 0 + * + * X = |a b c d e f g h i j k l m n o|^t +*/ +bool Homography3DFromCorrespondencesLinear(const Mat &x1, + const Mat &x2, + Mat4 *H, + double expected_precision) { + assert(4 == x1.rows()); + assert(5 <= x1.cols()); + assert(x1.rows() == x2.rows()); + assert(x1.cols() == x2.cols()); + const int x = 0; + const int y = 1; + const int z = 2; + const int w = 3; + int n = x1.cols(); + MatX15 L = Mat::Zero(n * 6, 15); + Mat b = Mat::Zero(n * 6, 1); + for (int i = 0; i < n; ++i) { + int j = 6 * i; + L(j, 0) = -x2(w, i) * x1(x, i);//a + L(j, 1) = -x2(w, i) * x1(y, i);//b + L(j, 2) = -x2(w, i) * x1(z, i);//c + L(j, 3) = -x2(w, i) * x1(w, i);//d + L(j,12) = x2(x, i) * x1(x, i);//m + L(j,13) = x2(x, i) * x1(y, i);//n + L(j,14) = x2(x, i) * x1(z, i);//o + b(j, 0) = -x2(x, i) * x1(w, i); + + ++j; + L(j, 4) = -x2(z, i) * x1(x, i);//e + L(j, 5) = -x2(z, i) * x1(y, i);//f + L(j, 6) = -x2(z, i) * x1(z, i);//g + L(j, 7) = -x2(z, i) * x1(w, i);//h + L(j, 8) = x2(y, i) * x1(x, i);//i + L(j, 9) = x2(y, i) * x1(y, i);//j + L(j,10) = x2(y, i) * x1(z, i);//k + L(j,11) = x2(y, i) * x1(w, i);//l + + ++j; + L(j, 0) = -x2(z, i) * x1(x, i);//a + L(j, 1) = -x2(z, i) * x1(y, i);//b + L(j, 2) = -x2(z, i) * x1(z, i);//c + L(j, 3) = -x2(z, i) * x1(w, i);//d + L(j, 8) = x2(x, i) * x1(x, i);//i + L(j, 9) = x2(x, i) * x1(y, i);//j + L(j,10) = x2(x, i) * x1(z, i);//k + L(j,11) = x2(x, i) * x1(w, i);//l + + ++j; + L(j, 4) = -x2(w, i) * x1(x, i);//e + L(j, 5) = -x2(w, i) * x1(y, i);//f + L(j, 6) = -x2(w, i) * x1(z, i);//g + L(j, 7) = -x2(w, i) * x1(w, i);//h + L(j,12) = x2(y, i) * x1(x, i);//m + L(j,13) = x2(y, i) * x1(y, i);//n + L(j,14) = x2(y, i) * x1(z, i);//o + b(j, 0) = -x2(y, i) * x1(w, i); + + ++j; + L(j, 0) = -x2(y, i) * x1(x, i);//a + L(j, 1) = -x2(y, i) * x1(y, i);//b + L(j, 2) = -x2(y, i) * x1(z, i);//c + L(j, 3) = -x2(y, i) * x1(w, i);//d + L(j, 4) = x2(x, i) * x1(x, i);//e + L(j, 5) = x2(x, i) * x1(y, i);//f + L(j, 6) = x2(x, i) * x1(z, i);//g + L(j, 7) = x2(x, i) * x1(w, i);//h + + ++j; + L(j, 8) = -x2(w, i) * x1(x, i);//i + L(j, 9) = -x2(w, i) * x1(y, i);//j + L(j,10) = -x2(w, i) * x1(z, i);//k + L(j,11) = -x2(w, i) * x1(w, i);//l + L(j,12) = x2(z, i) * x1(x, i);//m + L(j,13) = x2(z, i) * x1(y, i);//n + L(j,14) = x2(z, i) * x1(z, i);//o + b(j, 0) = -x2(z, i) * x1(w, i); + } + // Solve Lx=B + Vec h = L.fullPivLu().solve(b); + if ((L * h).isApprox(b, expected_precision)) { + Homography3DNormalizedParameterization::To(h, H); + return true; + } else { + return false; + } +} +} // namespace libmv diff --git a/extern/libmv/libmv/multiview/homography.h b/extern/libmv/libmv/multiview/homography.h new file mode 100644 index 00000000000..786fd3df8ca --- /dev/null +++ b/extern/libmv/libmv/multiview/homography.h @@ -0,0 +1,84 @@ +// Copyright (c) 2011 libmv authors. +// +// 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. + +#ifndef LIBMV_MULTIVIEW_HOMOGRAPHY_H_ +#define LIBMV_MULTIVIEW_HOMOGRAPHY_H_ + +#include "libmv/numeric/numeric.h" + +namespace libmv { + +/** + * 2D homography transformation estimation. + * + * This function estimates the homography transformation from a list of 2D + * correspondences which represents either: + * + * - 3D points on a plane, with a general moving camera. + * - 3D points with a rotating camera (pure rotation). + * - 3D points + different planar projections + * + * \param x1 The first 2xN or 3xN matrix of euclidean or homogeneous points. + * \param x2 The second 2xN or 3xN matrix of euclidean or homogeneous points. + * \param H The 3x3 homography transformation matrix (8 dof) such that + * x2 = H * x1 with |a b c| + * H = |d e f| + * |g h 1| + * \param expected_precision The expected precision in order for instance + * to accept almost homography matrices. + * + * \return True if the transformation estimation has succeeded. + * \note There must be at least 4 non-colinear points. + */ +bool Homography2DFromCorrespondencesLinear(const Mat &x1, + const Mat &x2, + Mat3 *H, + double expected_precision = + EigenDouble::dummy_precision()); + +/** + * 3D Homography transformation estimation. + * + * This function can be used in order to estimate the homography transformation + * from a list of 3D correspondences. + * + * \param[in] x1 The first 4xN matrix of homogeneous points + * \param[in] x2 The second 4xN matrix of homogeneous points + * \param[out] H The 4x4 homography transformation matrix (15 dof) such that + * x2 = H * x1 with |a b c d| + * H = |e f g h| + * |i j k l| + * |m n o 1| + * \param[in] expected_precision The expected precision in order for instance + * to accept almost homography matrices. + * + * \return true if the transformation estimation has succeeded + * + * \note Need at least 5 non coplanar points + * \note Points coordinates must be in homogeneous coordinates + */ +bool Homography3DFromCorrespondencesLinear(const Mat &x1, + const Mat &x2, + Mat4 *H, + double expected_precision = + EigenDouble::dummy_precision()); +} // namespace libmv + +#endif // LIBMV_MULTIVIEW_HOMOGRAPHY_H_ diff --git a/extern/libmv/libmv/multiview/homography_parameterization.h b/extern/libmv/libmv/multiview/homography_parameterization.h new file mode 100644 index 00000000000..b31642eea15 --- /dev/null +++ b/extern/libmv/libmv/multiview/homography_parameterization.h @@ -0,0 +1,91 @@ +// Copyright (c) 2011 libmv authors. +// +// 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. + +#ifndef LIBMV_MULTIVIEW_HOMOGRAPHY_PARAMETERIZATION_H_ +#define LIBMV_MULTIVIEW_HOMOGRAPHY_PARAMETERIZATION_H_ + +#include "libmv/numeric/numeric.h" + +namespace libmv { + +/** A parameterization of the 2D homography matrix that uses 8 parameters so + * that the matrix is normalized (H(2,2) == 1). + * The homography matrix H is built from a list of 8 parameters (a, b,...g, h) + * as follows + * |a b c| + * H = |d e f| + * |g h 1| + */ +template +class Homography2DNormalizedParameterization { + public: + typedef Eigen::Matrix Parameters; // a, b, ... g, h + typedef Eigen::Matrix Parameterized; // H + + /// Convert from the 8 parameters to a H matrix. + static void To(const Parameters &p, Parameterized *h) { + *h << p(0), p(1), p(2), + p(3), p(4), p(5), + p(6), p(7), 1.0; + } + + /// Convert from a H matrix to the 8 parameters. + static void From(const Parameterized &h, Parameters *p) { + *p << h(0, 0), h(0, 1), h(0, 2), + h(1, 0), h(1, 1), h(1, 2), + h(2, 0), h(2, 1); + } +}; + +/** A parameterization of the 2D homography matrix that uses 15 parameters so + * that the matrix is normalized (H(3,3) == 1). + * The homography matrix H is built from a list of 15 parameters (a, b,...n, o) + * as follows + * |a b c d| + * H = |e f g h| + * |i j k l| + * |m n o 1| + */ +template +class Homography3DNormalizedParameterization { + public: + typedef Eigen::Matrix Parameters; // a, b, ... n, o + typedef Eigen::Matrix Parameterized; // H + + /// Convert from the 15 parameters to a H matrix. + static void To(const Parameters &p, Parameterized *h) { + *h << p(0), p(1), p(2), p(3), + p(4), p(5), p(6), p(7), + p(8), p(9), p(10), p(11), + p(12), p(13), p(14), 1.0; + } + + /// Convert from a H matrix to the 15 parameters. + static void From(const Parameterized &h, Parameters *p) { + *p << h(0, 0), h(0, 1), h(0, 2), h(0, 3), + h(1, 0), h(1, 1), h(1, 2), h(1, 3), + h(2, 0), h(2, 1), h(2, 2), h(2, 3), + h(3, 0), h(3, 1), h(3, 2); + } +}; + +} // namespace libmv + +#endif // LIBMV_MULTIVIEW_HOMOGRAPHY_PARAMETERIZATION_H_ diff --git a/extern/libmv/libmv/tracking/esm_region_tracker.cc b/extern/libmv/libmv/tracking/esm_region_tracker.cc index 221fa4d081b..2491b158154 100644 --- a/extern/libmv/libmv/tracking/esm_region_tracker.cc +++ b/extern/libmv/libmv/tracking/esm_region_tracker.cc @@ -29,6 +29,7 @@ #include "libmv/image/correlation.h" #include "libmv/image/sample.h" #include "libmv/numeric/numeric.h" +#include "libmv/tracking/track_region.h" namespace libmv { @@ -72,6 +73,45 @@ bool EsmRegionTracker::Track(const FloatImage &image1, return false; } + // XXX + // TODO(keir): Delete the block between the XXX's once the planar tracker is + // integrated into blender. + // + // For now, to test, replace the ESM tracker with the Ceres tracker in + // translation mode. In the future, this should get removed and alloed to + // co-exist, since Ceres is not as fast as the ESM implementation since it + // specializes for translation. + double xx1[4], yy1[4]; + double xx2[4], yy2[4]; + // Clockwise winding, starting from the "origin" (top-left). + xx1[0] = xx2[0] = x1 - half_window_size; + yy1[0] = yy2[0] = y1 - half_window_size; + + xx1[1] = xx2[1] = x1 + half_window_size; + yy1[1] = yy2[1] = y1 - half_window_size; + + xx1[2] = xx2[2] = x1 + half_window_size; + yy1[2] = yy2[2] = y1 + half_window_size; + + xx1[3] = xx2[3] = x1 - half_window_size; + yy1[3] = yy2[3] = y1 + half_window_size; + + TrackRegionOptions options; + options.mode = TrackRegionOptions::TRANSLATION; + options.num_samples_x = 2 * half_window_size + 1; + options.num_samples_y = 2 * half_window_size + 1; + options.max_iterations = 20; + options.sigma = sigma; + + TrackRegionResult result; + TrackRegion(image1, image2, xx1, yy1, options, xx2, yy2, &result); + + *x2 = xx2[0] + half_window_size; + *y2 = yy2[0] + half_window_size; + + return true; + + // XXX int width = 2 * half_window_size + 1; // TODO(keir): Avoid recomputing gradients for e.g. the pyramid tracker. diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc new file mode 100644 index 00000000000..5a46c66cd3c --- /dev/null +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -0,0 +1,651 @@ +// Copyright (c) 2012 libmv authors. +// +// 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. +// +// Author: mierle@google.com (Keir Mierle) + +// Necessary for M_E when building with MSVC. +#define _USE_MATH_DEFINES + +#include "libmv/tracking/track_region.h" + +#include +#include +#include +#include "ceres/ceres.h" +#include "libmv/logging/logging.h" +#include "libmv/image/image.h" +#include "libmv/image/sample.h" +#include "libmv/image/convolve.h" +#include "libmv/multiview/homography.h" +#include "libmv/numeric/numeric.h" + +namespace libmv { + +// TODO(keir): Consider adding padding. +template +bool InBounds(const FloatImage &image, + const T &x, + const T &y) { + return 0.0 <= x && x < image.Width() && + 0.0 <= y && y < image.Height(); +} + +bool AllInBounds(const FloatImage &image, + const double *x, + const double *y) { + for (int i = 0; i < 4; ++i) { + if (!InBounds(image, x[i], y[i])) { + return false; + } + } + return true; +} + +// Because C++03 doesn't support partial template specializations for +// functions, but at the same time member function specializations are not +// supported, the sample function must be inside a template-specialized class +// with a non-templated static member. + +// The "AutoDiffImage::Sample()" function allows sampling an image at an x, y +// position such that if x and y are jets, then the derivative information is +// correctly propagated. + +// Empty default template. +template +struct AutoDiffImage { + static T Sample(const FloatImage &image_and_gradient, + const T &x, const T &y) { + return 0.0; + } +}; + +// Sample only the image when the coordinates are scalars. +template<> +struct AutoDiffImage { + static double Sample(const FloatImage &image_and_gradient, + const double& x, const double& y) { + return SampleLinear(image_and_gradient, y, x, 0); + } +}; + +// Sample the image and gradient when the coordinates are jets, applying the +// jacobian appropriately to propagate the derivatives from the coordinates. +template<> +template +struct AutoDiffImage > { + static ceres::Jet Sample(const FloatImage &image_and_gradient, + const ceres::Jet &x, + const ceres::Jet &y) { + // Sample the image and its derivatives in x and y. One way to think of + // this is that the image is a scalar function with a single vector + // argument, xy, of dimension 2. Call this s(xy). + const T s = SampleLinear(image_and_gradient, y.a, x.a, 0); + const T dsdx = SampleLinear(image_and_gradient, y.a, x.a, 1); + const T dsdy = SampleLinear(image_and_gradient, y.a, x.a, 2); + + // However, xy is itself a function of another variable ("z"); xy(z) = + // [x(z), y(z)]^T. What this function needs to return is "s", but with the + // derivative with respect to z attached to the jet. So combine the + // derivative part of x and y's jets to form a Jacobian matrix between x, y + // and z (i.e. dxy/dz). + Eigen::Matrix dxydz; + dxydz.row(0) = x.v.transpose(); + dxydz.row(1) = y.v.transpose(); + + // Now apply the chain rule to obtain ds/dz. Combine the derivative with + // the scalar part to obtain s with full derivative information. + ceres::Jet jet_s; + jet_s.a = s; + jet_s.v = Matrix(dsdx, dsdy) * dxydz; + return jet_s; + } +}; + +template +class BoundaryCheckingCallback : public ceres::IterationCallback { + public: + BoundaryCheckingCallback(const FloatImage& image2, + const Warp &warp, + const double *x1, const double *y1) + : image2_(image2), warp_(warp), x1_(x1), y1_(y1) {} + + virtual ceres::CallbackReturnType operator()( + const ceres::IterationSummary& summary) { + // Warp the original 4 points with the current warp into image2. + double x2[4]; + double y2[4]; + for (int i = 0; i < 4; ++i) { + warp_.Forward(warp_.parameters, x1_[i], y1_[i], x2 + i, y2 + i); + } + // Enusre they are all in bounds. + if (!AllInBounds(image2_, x2, y2)) { + return ceres::SOLVER_ABORT; + } + return ceres::SOLVER_CONTINUE; + } + + private: + const FloatImage &image2_; + const Warp &warp_; + const double *x1_; + const double *y1_; +}; + +template +class WarpCostFunctor { + public: + WarpCostFunctor(const FloatImage &image_and_gradient1, + const FloatImage &image_and_gradient2, + const Mat3 &canonical_to_image1, + const Warp &warp, + int num_samples_x, + int num_samples_y) + : image_and_gradient1_(image_and_gradient1), + image_and_gradient2_(image_and_gradient2), + canonical_to_image1_(canonical_to_image1), + warp_(warp), + num_samples_x_(num_samples_x), + num_samples_y_(num_samples_y) {} + + template + bool operator()(const T *warp_parameters, T *residuals) const { + for (int i = 0; i < Warp::NUM_PARAMETERS; ++i) { + VLOG(2) << "warp_parameters[" << i << "]: " << warp_parameters[i]; + } + + int cursor = 0; + for (int r = 0; r < num_samples_y_; ++r) { + for (int c = 0; c < num_samples_x_; ++c) { + // Compute the location of the source pixel (via homography). + Vec3 image1_position = canonical_to_image1_ * Vec3(c, r, 1); + image1_position /= image1_position(2); + + // Compute the location of the destination pixel. + T image2_position[2]; + warp_.Forward(warp_parameters, + T(image1_position[0]), + T(image1_position[1]), + &image2_position[0], + &image2_position[1]); + + // Sample the source and destination. + double src_sample = AutoDiffImage::Sample(image_and_gradient1_, + image1_position[0], + image1_position[1]); + T dst_sample = AutoDiffImage::Sample(image_and_gradient2_, + image2_position[0], + image2_position[1]); + + // The difference is the error. + residuals[cursor++] = T(src_sample) - dst_sample; + } + } + return true; + } + + private: + const FloatImage &image_and_gradient1_; + const FloatImage &image_and_gradient2_; + const Mat3 &canonical_to_image1_; + const Warp &warp_; + int num_samples_x_; + int num_samples_y_; +}; + +// Compute the warp from rectangular coordinates, where one corner is the +// origin, and the opposite corner is at (num_samples_x, num_samples_y). +Mat3 ComputeCanonicalHomography(const double *x1, + const double *y1, + int num_samples_x, + int num_samples_y) { + Mat canonical(2, 4); + canonical << 0, num_samples_x, num_samples_x, 0, + 0, 0, num_samples_y, num_samples_y; + + Mat xy1(2, 4); + xy1 << x1[0], x1[1], x1[2], x1[3], + y1[0], y1[1], y1[2], y1[3]; + + Mat3 H; + if (!Homography2DFromCorrespondencesLinear(canonical, xy1, &H, 1e-12)) { + LG << "Couldn't construct homography."; + } + return H; +} + +class Quad { + public: + Quad(const double *x, const double *y) + : x_(x), y_(y) { + + // Compute the centroid and store it. + centroid_ = Vec2(0.0, 0.0); + for (int i = 0; i < 4; ++i) { + centroid_ += Vec2(x_[i], y_[i]); + } + centroid_ /= 4.0; + } + + // The centroid of the four points representing the quad. + const Vec2& Centroid() const { + return centroid_; + } + + // The average magnitude of the four points relative to the centroid. + double Scale() const { + double scale = 0.0; + for (int i = 0; i < 4; ++i) { + scale += (Vec2(x_[i], y_[i]) - Centroid()).norm(); + } + return scale / 4.0; + } + + Vec2 CornerRelativeToCentroid(int i) const { + return Vec2(x_[i], y_[i]) - centroid_; + } + + private: + const double *x_; + const double *y_; + Vec2 centroid_; +}; + +struct TranslationWarp { + TranslationWarp(const double *x1, const double *y1, + const double *x2, const double *y2) { + Vec2 t = Quad(x1, y1).Centroid() - Quad(x2, y2).Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + } + + template + void Forward(const T *warp_parameters, + const T &x1, const T& y1, T *x2, T* y2) const { + *x2 = x1 + warp_parameters[0]; + *y2 = y1 + warp_parameters[1]; + } + + // Translation x, translation y. + enum { NUM_PARAMETERS = 2 }; + double parameters[NUM_PARAMETERS]; +}; + +struct TranslationScaleWarp { + TranslationScaleWarp(const double *x1, const double *y1, + const double *x2, const double *y2) + : q1(x1, y1) { + Quad q2(x2, y2); + + // The difference in centroids is the best guess for translation. + Vec2 t = q1.Centroid() - q2.Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + + // The difference in scales is the estimate for the scale. + parameters[2] = 1.0 - q2.Scale() / q1.Scale(); + } + + // The strange way of parameterizing the translation and scaling is to make + // the knobs that the optimizer sees easy to adjust. This is less important + // for the scaling case than the rotation case. + template + void Forward(const T *warp_parameters, + const T &x1, const T& y1, T *x2, T* y2) const { + // Make the centroid of Q1 the origin. + const T x1_origin = x1 - q1.Centroid()(0); + const T y1_origin = y1 - q1.Centroid()(1); + + // Scale uniformly about the origin. + const T scale = 1.0 + warp_parameters[2]; + const T x1_origin_scaled = scale * x1_origin; + const T y1_origin_scaled = scale * y1_origin; + + // Translate back into the space of Q1 (but scaled). + const T x1_scaled = x1_origin_scaled + q1.Centroid()(0); + const T y1_scaled = y1_origin_scaled + q1.Centroid()(1); + + // Translate into the space of Q2. + *x2 = x1_scaled + warp_parameters[0]; + *y2 = y1_scaled + warp_parameters[1]; + } + + // Translation x, translation y, scale. + enum { NUM_PARAMETERS = 3 }; + double parameters[NUM_PARAMETERS]; + + Quad q1; +}; + +// Assumes the given points are already zero-centroid and the same size. +Mat2 OrthogonalProcrustes(const Mat2 &correlation_matrix) { + Eigen::JacobiSVD svd(correlation_matrix, + Eigen::ComputeFullU | Eigen::ComputeFullV); + return svd.matrixV() * svd.matrixU().transpose(); +} + +struct TranslationRotationWarp { + TranslationRotationWarp(const double *x1, const double *y1, + const double *x2, const double *y2) + : q1(x1, y1) { + Quad q2(x2, y2); + + // The difference in centroids is the best guess for translation. + Vec2 t = q1.Centroid() - q2.Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + + // Obtain the rotation via orthorgonal procrustes. + Mat2 correlation_matrix; + for (int i = 0; i < 4; ++i) { + correlation_matrix += q1.CornerRelativeToCentroid(i) * + q2.CornerRelativeToCentroid(i).transpose(); + } + Mat2 R = OrthogonalProcrustes(correlation_matrix); + parameters[2] = acos(R(0, 0)); + } + + // The strange way of parameterizing the translation and rotation is to make + // the knobs that the optimizer sees easy to adjust. The reason is that while + // it is always the case that it is possible to express composed rotations + // and translations as a single translation and rotation, the numerical + // values needed for the composition are often large in magnitude. This is + // enough to throw off any minimizer, since it must do the equivalent of + // compose rotations and translations. + // + // Instead, use the parameterization below that offers a parameterization + // that exposes the degrees of freedom in a way amenable to optimization. + template + void Forward(const T *warp_parameters, + const T &x1, const T& y1, T *x2, T* y2) const { + // Make the centroid of Q1 the origin. + const T x1_origin = x1 - q1.Centroid()(0); + const T y1_origin = y1 - q1.Centroid()(1); + + // Rotate about the origin (i.e. centroid of Q1). + const T theta = warp_parameters[2]; + const T costheta = cos(theta); + const T sintheta = sin(theta); + const T x1_origin_rotated = costheta * x1_origin - sintheta * y1_origin; + const T y1_origin_rotated = sintheta * x1_origin + costheta * y1_origin; + + // Translate back into the space of Q1 (but scaled). + const T x1_rotated = x1_origin_rotated + q1.Centroid()(0); + const T y1_rotated = y1_origin_rotated + q1.Centroid()(1); + + // Translate into the space of Q2. + *x2 = x1_rotated + warp_parameters[0]; + *y2 = y1_rotated + warp_parameters[1]; + } + + // Translation x, translation y, rotation about the center of Q1 degrees. + enum { NUM_PARAMETERS = 3 }; + double parameters[NUM_PARAMETERS]; + + Quad q1; +}; + +struct TranslationRotationScaleWarp { + TranslationRotationScaleWarp(const double *x1, const double *y1, + const double *x2, const double *y2) + : q1(x1, y1) { + Quad q2(x2, y2); + + // The difference in centroids is the best guess for translation. + Vec2 t = q1.Centroid() - q2.Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + + // The difference in scales is the estimate for the scale. + parameters[2] = 1.0 - q2.Scale() / q1.Scale(); + + // Obtain the rotation via orthorgonal procrustes. + Mat2 correlation_matrix; + for (int i = 0; i < 4; ++i) { + correlation_matrix += q1.CornerRelativeToCentroid(i) * + q2.CornerRelativeToCentroid(i).transpose(); + } + Mat2 R = OrthogonalProcrustes(correlation_matrix); + parameters[3] = acos(R(0, 0)); + } + + // The strange way of parameterizing the translation and rotation is to make + // the knobs that the optimizer sees easy to adjust. The reason is that while + // it is always the case that it is possible to express composed rotations + // and translations as a single translation and rotation, the numerical + // values needed for the composition are often large in magnitude. This is + // enough to throw off any minimizer, since it must do the equivalent of + // compose rotations and translations. + // + // Instead, use the parameterization below that offers a parameterization + // that exposes the degrees of freedom in a way amenable to optimization. + template + void Forward(const T *warp_parameters, + const T &x1, const T& y1, T *x2, T* y2) const { + // Make the centroid of Q1 the origin. + const T x1_origin = x1 - q1.Centroid()(0); + const T y1_origin = y1 - q1.Centroid()(1); + + // Rotate about the origin (i.e. centroid of Q1). + const T theta = warp_parameters[2]; + const T costheta = cos(theta); + const T sintheta = sin(theta); + const T x1_origin_rotated = costheta * x1_origin - sintheta * y1_origin; + const T y1_origin_rotated = sintheta * x1_origin + costheta * y1_origin; + + // Scale uniformly about the origin. + const T scale = 1.0 + warp_parameters[2]; + const T x1_origin_rotated_scaled = scale * x1_origin_rotated; + const T y1_origin_rotated_scaled = scale * y1_origin_rotated; + + // Translate back into the space of Q1 (but scaled and rotated). + const T x1_rotated_scaled = x1_origin_rotated_scaled + q1.Centroid()(0); + const T y1_rotated_scaled = y1_origin_rotated_scaled + q1.Centroid()(1); + + // Translate into the space of Q2. + *x2 = x1_rotated_scaled + warp_parameters[0]; + *y2 = y1_rotated_scaled + warp_parameters[1]; + } + + // Translation x, translation y, rotation about the center of Q1 degrees, + // scale. + enum { NUM_PARAMETERS = 4 }; + double parameters[NUM_PARAMETERS]; + + Quad q1; +}; + +// TODO(keir): Finish affine warp. + +struct HomographyWarp { + HomographyWarp(const double *x1, const double *y1, + const double *x2, const double *y2) { + Mat quad1(2, 4); + quad1 << x1[0], x1[1], x1[2], x1[3], + y1[0], y1[1], y1[2], y1[3]; + + Mat quad2(2, 4); + quad2 << x2[0], x2[1], x2[2], x2[3], + y2[0], y2[1], y2[2], y2[3]; + + Mat3 H; + if (!Homography2DFromCorrespondencesLinear(quad1, quad2, &H, 1e-12)) { + LG << "Couldn't construct homography."; + } + + // Assume H(2, 2) != 0, and fix scale at H(2, 2) == 1.0. + H /= H(2, 2); + + // Assume H is close to identity, so subtract out the diagonal. + H(0, 0) -= 1.0; + H(1, 1) -= 1.0; + + CHECK_NE(H(2, 2), 0.0) << H; + for (int i = 0; i < 8; ++i) { + parameters[i] = H(i / 3, i % 3); + LG << "Parameters[" << i << "]: " << parameters[i]; + } + } + + template + static void Forward(const T *p, + const T &x1, const T& y1, T *x2, T* y2) { + // Homography warp with manual 3x3 matrix multiply. + const T xx2 = (1.0 + p[0]) * x1 + p[1] * y1 + p[2]; + const T yy2 = p[3] * x1 + (1.0 + p[4]) * y1 + p[5]; + const T zz2 = p[6] * x1 + p[7] * y1 + 1.0; + *x2 = xx2 / zz2; + *y2 = yy2 / zz2; + } + + enum { NUM_PARAMETERS = 8 }; + double parameters[NUM_PARAMETERS]; +}; + +template +void TemplatedTrackRegion(const FloatImage &image1, + const FloatImage &image2, + const double *x1, const double *y1, + const TrackRegionOptions &options, + double *x2, double *y2, + TrackRegionResult *result) { + // Bail early if the points are already outside. + if (!AllInBounds(image1, x1, y1)) { + result->termination = TrackRegionResult::SOURCE_OUT_OF_BOUNDS; + return; + } + if (!AllInBounds(image2, x2, y2)) { + result->termination = TrackRegionResult::DESTINATION_OUT_OF_BOUNDS; + return; + } + // TODO(keir): Check quads to ensure there is some area. + + // Prepare the image and gradient. + Array3Df image_and_gradient1; + Array3Df image_and_gradient2; + BlurredImageAndDerivativesChannels(image1, options.sigma, + &image_and_gradient1); + BlurredImageAndDerivativesChannels(image2, options.sigma, + &image_and_gradient2); + + // Prepare the initial warp parameters from the four correspondences. + Warp warp(x1, y1, x2, y2); + + ceres::Solver::Options solver_options; + solver_options.linear_solver_type = ceres::DENSE_QR; + solver_options.max_num_iterations = options.max_iterations; + solver_options.update_state_every_iteration = true; + solver_options.parameter_tolerance = 1e-16; + solver_options.function_tolerance = 1e-16; + + // TODO(keir): Consider removing these options before committing. + solver_options.numeric_derivative_relative_step_size = 1e-3; + solver_options.gradient_check_relative_precision = 1e-10; + solver_options.minimizer_progress_to_stdout = false; + + // Prevent the corners from going outside the destination image. + BoundaryCheckingCallback callback(image2, warp, x1, y1); + solver_options.callbacks.push_back(&callback); + + // Compute the warp from rectangular coordinates. + Mat3 canonical_homography = ComputeCanonicalHomography(x1, y1, + options.num_samples_x, + options.num_samples_y); + + // Construct the warp cost function. AutoDiffCostFunction takes ownership. + WarpCostFunctor *cost_function = + new WarpCostFunctor(image_and_gradient1, + image_and_gradient2, + canonical_homography, + warp, + options.num_samples_x, + options.num_samples_y); + + // Construct the problem with a single residual. + ceres::Problem::Options problem_options; + problem_options.cost_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; + ceres::Problem problem(problem_options); + problem.AddResidualBlock( + new ceres::AutoDiffCostFunction< + WarpCostFunctor, + ceres::DYNAMIC, + Warp::NUM_PARAMETERS>(cost_function, + options.num_samples_x * options.num_samples_y), + NULL, + warp.parameters); + + ceres::Solver::Summary summary; + ceres::Solve(solver_options, &problem, &summary); + + LG << "Summary:\n" << summary.FullReport(); + + // Update the four points with the found solution; if the solver failed, then + // the warp parameters are the identity (so ignore failure). + for (int i = 0; i < 4; ++i) { + warp.Forward(warp.parameters, x1[i], y1[i], x2 + i, y2 + i); + } + + // TODO(keir): Update the result statistics. + + CHECK_NE(summary.termination_type, ceres::USER_ABORT) << "Libmv bug."; + if (summary.termination_type == ceres::USER_ABORT) { + result->termination = TrackRegionResult::FELL_OUT_OF_BOUNDS; + return; + } +#define HANDLE_TERMINATION(termination_enum) \ + if (summary.termination_type == ceres::termination_enum) { \ + result->termination = TrackRegionResult::termination_enum; \ + return; \ + } + HANDLE_TERMINATION(PARAMETER_TOLERANCE); + HANDLE_TERMINATION(FUNCTION_TOLERANCE); + HANDLE_TERMINATION(GRADIENT_TOLERANCE); + HANDLE_TERMINATION(NO_CONVERGENCE); + HANDLE_TERMINATION(DID_NOT_RUN); + HANDLE_TERMINATION(NUMERICAL_FAILURE); +#undef HANDLE_TERMINATION +}; + +void TrackRegion(const FloatImage &image1, + const FloatImage &image2, + const double *x1, const double *y1, + const TrackRegionOptions &options, + double *x2, double *y2, + TrackRegionResult *result) { + // Enum is necessary due to templated nature of autodiff. +#define HANDLE_MODE(mode_enum, mode_type) \ + if (options.mode == TrackRegionOptions::mode_enum) { \ + TemplatedTrackRegion(image1, image2, \ + x1, y1, \ + options, \ + x2, y2, \ + result); \ + return; \ + } + + HANDLE_MODE(TRANSLATION, TranslationWarp); + HANDLE_MODE(TRANSLATION_SCALE, TranslationScaleWarp); + HANDLE_MODE(TRANSLATION_ROTATION, TranslationRotationWarp); + HANDLE_MODE(TRANSLATION_ROTATION_SCALE, TranslationRotationScaleWarp); + //HANDLE_MODE(AFFINE, AffineWarp); + HANDLE_MODE(HOMOGRAPHY, HomographyWarp); +#undef HANDLE_MODE +} + +} // namespace libmv diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h new file mode 100644 index 00000000000..ca783c32a75 --- /dev/null +++ b/extern/libmv/libmv/tracking/track_region.h @@ -0,0 +1,91 @@ +// Copyright (c) 2012 libmv authors. +// +// 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. + +#ifndef LIBMV_TRACKING_TRACK_REGION_H_ + +// Necessary for M_E when building with MSVC. +#define _USE_MATH_DEFINES + +#include "libmv/tracking/esm_region_tracker.h" + +#include "libmv/image/image.h" +#include "libmv/image/sample.h" +#include "libmv/numeric/numeric.h" + +namespace libmv { + +struct TrackRegionOptions { + enum Mode { + TRANSLATION, + TRANSLATION_ROTATION, + TRANSLATION_SCALE, + TRANSLATION_ROTATION_SCALE, + AFFINE, + HOMOGRAPHY, + }; + Mode mode; + + int num_samples_x; + int num_samples_y; + + double minimum_correlation; + int max_iterations; + bool use_esm; + + double sigma; +}; + +struct TrackRegionResult { + enum Termination { + // Ceres termination types, duplicated. + PARAMETER_TOLERANCE = 0, + FUNCTION_TOLERANCE, + GRADIENT_TOLERANCE, + NO_CONVERGENCE, + DID_NOT_RUN, + NUMERICAL_FAILURE, + + // Libmv specific errors. + SOURCE_OUT_OF_BOUNDS, + DESTINATION_OUT_OF_BOUNDS, + FELL_OUT_OF_BOUNDS, + INSUFFICIENT_CORRELATION, + }; + Termination termination; + + int num_iterations; + double correlation; + + // Final parameters? +}; + +// Always needs 4 correspondences. +void TrackRegion(const FloatImage &image1, + const FloatImage &image2, + const double *x1, const double *y1, + const TrackRegionOptions &options, + double *x2, double *y2, + TrackRegionResult *result); + +// TODO(keir): May need a "samplewarp" function. + +} // namespace libmv + +#endif // LIBMV_TRACKING_TRACK_REGION_H_ From 4f81bdf73cf31e70bdf77701c7201471c659e060 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Mon, 14 May 2012 10:47:25 +0000 Subject: [PATCH 036/183] Start migrating away from pat_min and pat_max for markers This starts converting markers in the movie clip editor / 2D tracker from using pat_min and pat_max notation to using the a more general, 4-corner representation. There is still considerable porting work to do; in particular: - The preview widget does not respect the new representation - The corners cannot yet be edited individually. - The clamping does not do the right thing for general corners; e.g. detecting a convex quad. - The tracking code in Blender does not actually invoke the corner tracking version of libmv's tracking API. Next steps: - Convert libmv's legacy ESM tracker and brute tracker to work under the new TrackRegion() API. - Make Blender use the new TrackRegion() API; this will allow real planar tracking tests. - Everything else (UI, etc). This patch is mostly the work of Sergey Sharybin. --- source/blender/blenkernel/BKE_tracking.h | 1 + source/blender/blenkernel/intern/movieclip.c | 12 +- source/blender/blenkernel/intern/tracking.c | 151 +++++++++++------- source/blender/blenloader/intern/readfile.c | 35 ++++ .../blender/editors/space_clip/clip_buttons.c | 32 ++-- source/blender/editors/space_clip/clip_draw.c | 63 +++++--- .../blender/editors/space_clip/space_clip.c | 6 +- .../blender/editors/space_clip/tracking_ops.c | 48 +++++- .../editors/transform/transform_conversions.c | 14 +- source/blender/makesdna/DNA_tracking_types.h | 24 ++- 10 files changed, 276 insertions(+), 110 deletions(-) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 817cb477aba..84beca4fd96 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -57,6 +57,7 @@ struct MovieTrackingMarker *BKE_tracking_insert_marker(struct MovieTrackingTrack struct MovieTrackingMarker *marker); void BKE_tracking_delete_marker(struct MovieTrackingTrack *track, int framenr); +void BKE_tracking_marker_pattern_minmax(struct MovieTrackingMarker *marker, float min[2], float max[2]); struct MovieTrackingMarker *BKE_tracking_get_marker(struct MovieTrackingTrack *track, int framenr); struct MovieTrackingMarker *BKE_tracking_ensure_marker(struct MovieTrackingTrack *track, int framenr); struct MovieTrackingMarker *BKE_tracking_exact_marker(struct MovieTrackingTrack *track, int framenr); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index f07de7f0127..952e87077dc 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1076,10 +1076,18 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip } if ((track->flag & TRACK_LOCKED) == 0) { + float pat_min[2], pat_max[2]; + scopes->marker = marker; scopes->track = track; - scopes->slide_scale[0] = track->pat_max[0] - track->pat_min[0]; - scopes->slide_scale[1] = track->pat_max[1] - track->pat_min[1]; + + /* XXX: would work fine with non-transformed patterns, but would likely fail + * with transformed patterns, but that would be easier to debug when + * we'll have real pattern sampling (at least to test) */ + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + scopes->slide_scale[0] = pat_max[0] - pat_min[0]; + scopes->slide_scale[1] = pat_max[1] - pat_min[1]; } } } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 4e2b4be474b..e8168da45fb 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -102,59 +102,67 @@ void BKE_tracking_init_settings(MovieTracking *tracking) void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) { int a; - float pat_min[2]; - float pat_max[2]; + float pat_min[2], pat_max[2]; + float eff_pat_min[2], eff_pat_max[2]; float max_pyramid_level_factor = 1.0; if (track->tracker == TRACKER_KLT) { max_pyramid_level_factor = 1 << (track->pyramid_levels - 1); } - /* sort */ - for (a = 0; a < 2; a++) { - if (track->pat_min[a] > track->pat_max[a]) - SWAP(float, track->pat_min[a], track->pat_max[a]); + /* XXX: currently search area is global, pattern size is per-marker, so we'll need to + * find maximal size of pattern to clamp search size nicely */ + INIT_MINMAX2(pat_min, pat_max); - if (track->search_min[a] > track->search_max[a]) - SWAP(float, track->search_min[a], track->search_max[a]); + for (a = 0; a < track->markersnr; a++) { + float cur_pat_min[2], cur_pat_max[2]; + + BKE_tracking_marker_pattern_minmax(&track->markers[a], cur_pat_min, cur_pat_max); + + DO_MINMAX2(cur_pat_min, pat_min, pat_max); + DO_MINMAX2(cur_pat_max, pat_min, pat_max); } /* compute the effective pattern size, which differs from the fine resolution * pattern size for the pyramid KLT tracker */ for (a = 0; a < 2; a++) { - pat_min[a] = max_pyramid_level_factor * track->pat_min[a]; - pat_max[a] = max_pyramid_level_factor * track->pat_max[a]; + eff_pat_min[a] = max_pyramid_level_factor * pat_min[a]; + eff_pat_max[a] = max_pyramid_level_factor * pat_max[a]; } if (event == CLAMP_PAT_DIM) { for (a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ - track->search_min[a] = MIN2(pat_min[a], track->search_min[a]); - track->search_max[a] = MAX2(pat_max[a], track->search_max[a]); + track->search_min[a] = MIN2(eff_pat_min[a], track->search_min[a]); + track->search_max[a] = MAX2(eff_pat_max[a], track->search_max[a]); } } else if (event == CLAMP_PAT_POS) { float dim[2]; - sub_v2_v2v2(dim, track->pat_max, track->pat_min); + sub_v2_v2v2(dim, pat_max, pat_min); +#if 0 + /* XXX: needs porting, but we need to know marker here, will be ported after a bit + * more global refactoring */ for (a = 0; a < 2; a++) { /* pattern shouldn't be moved outside of search */ - if (pat_min[a] < track->search_min[a]) { - track->pat_min[a] = track->search_min[a] - (pat_min[a] - track->pat_min[a]); + if (eff_pat_min[a] < track->search_min[a]) { + track->pat_min[a] = track->search_min[a] - (eff_pat_min[a] - pat_min[a]); track->pat_max[a] = track->pat_min[a] + dim[a]; } - if (track->pat_max[a] > track->search_max[a]) { - track->pat_max[a] = track->search_max[a] - (pat_max[a] - track->pat_max[a]); + if (eff_pat_max[a] > track->search_max[a]) { + track->pat_max[a] = track->search_max[a] - (eff_pat_max[a] - pat_max[a]); track->pat_min[a] = track->pat_max[a] - dim[a]; } } +#endif } else if (event == CLAMP_SEARCH_DIM) { for (a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ - track->search_min[a] = MIN2(pat_min[a], track->search_min[a]); - track->search_max[a] = MAX2(pat_max[a], track->search_max[a]); + track->search_min[a] = MIN2(eff_pat_min[a], track->search_min[a]); + track->search_max[a] = MAX2(eff_pat_max[a], track->search_max[a]); } } else if (event == CLAMP_SEARCH_POS) { @@ -164,42 +172,30 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) for (a = 0; a < 2; a++) { /* search shouldn't be moved inside pattern */ - if (track->search_min[a] > pat_min[a]) { - track->search_min[a] = pat_min[a]; + if (track->search_min[a] > eff_pat_min[a]) { + track->search_min[a] = eff_pat_min[a]; track->search_max[a] = track->search_min[a] + dim[a]; } - if (track->search_max[a] < pat_max[a]) { - track->search_max[a] = pat_max[a]; + if (track->search_max[a] < eff_pat_max[a]) { + track->search_max[a] = eff_pat_max[a]; track->search_min[a] = track->search_max[a] - dim[a]; } } } else if (event == CLAMP_PYRAMID_LEVELS || (event == CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT)) { float dim[2]; - sub_v2_v2v2(dim, track->pat_max, track->pat_min); + sub_v2_v2v2(dim, pat_max, pat_min); { float search_ratio = 2.3f * max_pyramid_level_factor; /* resize the search area to something sensible based * on the number of pyramid levels */ for (a = 0; a < 2; a++) { - track->search_min[a] = search_ratio * track->pat_min[a]; - track->search_max[a] = search_ratio * track->pat_max[a]; + track->search_min[a] = search_ratio * pat_min[a]; + track->search_max[a] = search_ratio * pat_max[a]; } } } - - /* marker's center should be in center of pattern */ - if (event == CLAMP_PAT_DIM || event == CLAMP_PAT_POS) { - float dim[2]; - - sub_v2_v2v2(dim, track->pat_max, track->pat_min); - - for (a = 0; a < 2; a++) { - track->pat_min[a] = -dim[a] / 2.0f; - track->pat_max[a] = dim[a] / 2.0f; - } - } } void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear) @@ -258,8 +254,14 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr marker.pos[1] = y; marker.framenr = framenr; - copy_v2_v2(track->pat_max, pat); - negate_v2_v2(track->pat_min, pat); + marker.pattern_corners[0][0] = -pat[0]; + marker.pattern_corners[0][1] = -pat[1]; + + marker.pattern_corners[1][0] = pat[0]; + marker.pattern_corners[1][1] = -pat[1]; + + negate_v2_v2(marker.pattern_corners[2], marker.pattern_corners[0]); + negate_v2_v2(marker.pattern_corners[3], marker.pattern_corners[1]); copy_v2_v2(track->search_max, search); negate_v2_v2(track->search_min, search); @@ -337,6 +339,16 @@ void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr) } } +void BKE_tracking_marker_pattern_minmax(MovieTrackingMarker *marker, float min[2], float max[2]) +{ + INIT_MINMAX2(min, max); + + DO_MINMAX2(marker->pattern_corners[0], min, max); + DO_MINMAX2(marker->pattern_corners[1], min, max); + DO_MINMAX2(marker->pattern_corners[2], min, max); + DO_MINMAX2(marker->pattern_corners[3], min, max); +} + MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr) { int a = track->markersnr - 1; @@ -1002,28 +1014,38 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u #ifdef WITH_LIBMV { - float patx = (int)((track->pat_max[0] - track->pat_min[0]) * width), - paty = (int)((track->pat_max[1] - track->pat_min[1]) * height); + float search_size_x, search_size_y; + float pattern_size_x, pattern_size_y; + float pat_min[2], pat_max[2], patx, paty; + float search_to_pattern_ratio, log2_search_to_pattern_ratio; + int wndx, wndy, half_wnd, max_pyramid_levels, level; - float search_size_x = (track->search_max[0] - track->search_min[0]) * width; - float search_size_y = (track->search_max[1] - track->search_min[1]) * height; - float pattern_size_x = (track->pat_max[0] - track->pat_min[0]) * width; - float pattern_size_y = (track->pat_max[1] - track->pat_min[1]) * height; - int wndx = (int)patx / 2, wndy = (int)paty / 2; - int half_wnd = MAX2(wndx, wndy); + struct libmv_RegionTracker *region_tracker; - /* compute the maximum pyramid size */ - float search_to_pattern_ratio = MIN2(search_size_x, search_size_y) - / MAX2(pattern_size_x, pattern_size_y); - float log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2; - int max_pyramid_levels = floor(log2_search_to_pattern_ratio + 1); + /* XXX: use boundbox of marker's pattern for now + * no idea how it should behave with non-affine tracking */ + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + patx = (int)((pat_max[0] - pat_min[0]) * width); + paty = (int)((pat_max[1] - pat_min[1]) * height); + wndx = (int)patx / 2; + wndy = (int)paty / 2; + half_wnd = MAX2(wndx, wndy); + + search_size_x = (track->search_max[0] - track->search_min[0]) * width; + search_size_y = (track->search_max[1] - track->search_min[1]) * height; + pattern_size_x = (pat_max[0] - pat_min[0]) * width; + pattern_size_y = (pat_max[1] - pat_min[1]) * height; + + /* compute the maximum pyramid size */ + search_to_pattern_ratio = MIN2(search_size_x, search_size_y) / MAX2(pattern_size_x, pattern_size_y); + log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2; + max_pyramid_levels = floor(log2_search_to_pattern_ratio + 1); /* try to accommodate the user's choice of pyramid level in a way * that doesn't cause the coarsest pyramid pattern to be larger * than the search size */ - int level = MIN2(track->pyramid_levels, max_pyramid_levels); - - struct libmv_RegionTracker *region_tracker; + level = MIN2(track->pyramid_levels, max_pyramid_levels); if (track->tracker == TRACKER_KLT) { region_tracker = libmv_pyramidRegionTrackerNew(100, level, half_wnd, @@ -1226,7 +1248,13 @@ static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTracki ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, int margin, int anchored, float pos[2], int origin[2]) { - return get_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin); + float pat_min[2], pat_max[2]; + + /* XXX: need to do real quad sampling here, but currently just assume + * corners represents quad pattern */ + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, margin, anchored, pos, origin); } ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, @@ -1430,7 +1458,7 @@ int BKE_tracking_next(MovieTrackingContext *context) if (marker && (marker->flag & MARKER_DISABLED) == 0) { #ifdef WITH_LIBMV int width, height, origin[2], tracked = 0, need_readjust = 0; - float pos[2], margin[2], dim[2]; + float pos[2], margin[2], dim[2], pat_min[2], pat_max[2]; double x1, y1, x2, y2; ImBuf *ibuf = NULL; MovieTrackingMarker marker_new, *marker_keyed; @@ -1447,7 +1475,8 @@ int BKE_tracking_next(MovieTrackingContext *context) nextfra = curfra + 1; /* margin from frame boundaries */ - sub_v2_v2v2(dim, track->pat_max, track->pat_min); + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + sub_v2_v2v2(dim, pat_max, pat_min); margin[0] = margin[1] = MAX2(dim[0], dim[1]) / 2.0f; margin[0] = MAX2(margin[0], (float)track->margin / ibuf_new->x); @@ -1509,6 +1538,10 @@ int BKE_tracking_next(MovieTrackingContext *context) copy_v2_v2(marker_new.pos, marker->pos); } + /* XXX: currently trackers does not change corners of a track, so + * just copy them from previous position */ + memcpy(marker_new.pattern_corners, marker->pattern_corners, sizeof(marker_new.pattern_corners)); + marker_new.flag |= MARKER_TRACKED; marker_new.framenr = nextfra; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 1e61aa937d6..79a09ab6c23 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7612,6 +7612,41 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + { + MovieClip *clip; + + for (clip = main->movieclip.first; clip; clip = clip->id.next) { + MovieTrackingTrack *track; + + track = clip->tracking.tracks.first; + while (track) { + int i; + + for (i = 0; i < track->markersnr; i++) { + MovieTrackingMarker *marker = &track->markers[i]; + + if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) && + is_zero_v2(marker->pattern_corners[3]) && is_zero_v2(marker->pattern_corners[3])) + { + marker->pattern_corners[0][0] = track->pat_min[0]; + marker->pattern_corners[0][1] = track->pat_min[1]; + + marker->pattern_corners[1][0] = track->pat_max[0]; + marker->pattern_corners[1][1] = track->pat_min[1]; + + marker->pattern_corners[2][0] = track->pat_max[0]; + marker->pattern_corners[2][1] = track->pat_max[1]; + + marker->pattern_corners[3][0] = track->pat_min[0]; + marker->pattern_corners[3][1] = track->pat_max[1]; + } + } + + track = track->next; + } + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 18f191a46a6..1f5e838f073 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -186,6 +186,7 @@ typedef struct { MovieClip *clip; MovieClipUser *user; /* user of clip */ MovieTrackingTrack *track; + MovieTrackingMarker *marker; int framenr; /* current frame number */ float marker_pos[2]; /* position of marker in pixel coords */ @@ -238,9 +239,11 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) ok = TRUE; } else if (event == B_MARKER_PAT_DIM) { - float dim[2], pat_dim[2]; + float dim[2], pat_dim[2], pat_min[2], pat_max[2]; - sub_v2_v2v2(pat_dim, cb->track->pat_max, cb->track->pat_min); + BKE_tracking_marker_pattern_minmax(cb->marker, pat_min, pat_max); + + sub_v2_v2v2(pat_dim, pat_max, pat_min); dim[0] = cb->track_pat[0] / width; dim[1] = cb->track_pat[1] / height; @@ -248,11 +251,17 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) sub_v2_v2(dim, pat_dim); mul_v2_fl(dim, 0.5f); - cb->track->pat_min[0] -= dim[0]; - cb->track->pat_min[1] -= dim[1]; + cb->marker->pattern_corners[0][0] -= dim[0]; + cb->marker->pattern_corners[0][1] -= dim[1]; - cb->track->pat_max[0] += dim[0]; - cb->track->pat_max[1] += dim[1]; + cb->marker->pattern_corners[1][0] += dim[0]; + cb->marker->pattern_corners[1][1] -= dim[1]; + + cb->marker->pattern_corners[2][0] += dim[0]; + cb->marker->pattern_corners[2][1] += dim[1]; + + cb->marker->pattern_corners[3][0] -= dim[0]; + cb->marker->pattern_corners[3][1] += dim[1]; BKE_tracking_clamp_track(cb->track, CLAMP_PAT_DIM); @@ -337,6 +346,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P MovieTrackingMarker *marker; MarkerUpdateCb *cb; const char *tip; + float pat_min[2], pat_max[2]; if (!ptr->data) return; @@ -366,6 +376,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P cb->clip = clip; cb->user = user; cb->track = track; + cb->marker = marker; cb->marker_flag = marker->flag; cb->framenr = user->framenr; @@ -383,7 +394,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P } else { int width, height, step, digits; - float pat_dim[2], pat_pos[2], search_dim[2], search_pos[2]; + float pat_dim[2], search_dim[2], search_pos[2]; uiLayout *col; BKE_movieclip_get_size(clip, user, &width, &height); @@ -399,15 +410,14 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P step = 100; digits = 2; - sub_v2_v2v2(pat_dim, track->pat_max, track->pat_min); + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + sub_v2_v2v2(pat_dim, pat_max, pat_min); sub_v2_v2v2(search_dim, track->search_max, track->search_min); add_v2_v2v2(search_pos, track->search_max, track->search_min); mul_v2_fl(search_pos, 0.5); - add_v2_v2v2(pat_pos, track->pat_max, track->pat_min); - mul_v2_fl(pat_pos, 0.5); - to_pixel_space(cb->marker_pos, marker->pos, width, height); to_pixel_space(cb->track_pat, pat_dim, width, height); to_pixel_space(cb->track_search, search_dim, width, height); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index f92f639586d..8a9d9313a6c 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -428,14 +428,17 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT if ((marker->flag & MARKER_DISABLED) == 0) { float pos[2]; - rctf r; + float p[2]; - BLI_init_rctf(&r, track->pat_min[0], track->pat_max[0], track->pat_min[1], track->pat_max[1]); add_v2_v2v2(pos, marker->pos, track->offset); ED_clip_point_undistorted_pos(sc, pos, pos); - if (BLI_in_rctf(&r, pos[0] - marker_pos[0], pos[1] - marker_pos[1])) { + sub_v2_v2v2(p, pos, marker_pos); + + if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1], + marker->pattern_corners[2], marker->pattern_corners[3])) + { if (tiny) glPointSize(3.0f); else glPointSize(4.0f); glBegin(GL_POINTS); @@ -471,10 +474,10 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT if (sc->flag & SC_SHOW_MARKER_PATTERN) { glBegin(GL_LINE_LOOP); - glVertex2f(track->pat_min[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_max[1]); - glVertex2f(track->pat_min[0], track->pat_max[1]); + glVertex2fv(marker->pattern_corners[0]); + glVertex2fv(marker->pattern_corners[1]); + glVertex2fv(marker->pattern_corners[2]); + glVertex2fv(marker->pattern_corners[3]); glEnd(); } @@ -528,8 +531,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra /* marker position and offset position */ if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) { - float pos[2]; - rctf r; + float pos[2], p[2]; if (track->flag & TRACK_LOCKED) { if (act) @@ -546,11 +548,14 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra glColor3fv(col); } - BLI_init_rctf(&r, track->pat_min[0], track->pat_max[0], track->pat_min[1], track->pat_max[1]); add_v2_v2v2(pos, marker->pos, track->offset); ED_clip_point_undistorted_pos(sc, pos, pos); - if (BLI_in_rctf(&r, pos[0] - marker_pos[0], pos[1] - marker_pos[1])) { + sub_v2_v2v2(p, pos, marker_pos); + + if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1], + marker->pattern_corners[2], marker->pattern_corners[3])) + { if (!tiny) glPointSize(2.0f); @@ -623,10 +628,10 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra } glBegin(GL_LINE_LOOP); - glVertex2f(track->pat_min[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_max[1]); - glVertex2f(track->pat_min[0], track->pat_max[1]); + glVertex2fv(marker->pattern_corners[0]); + glVertex2fv(marker->pattern_corners[1]); + glVertex2fv(marker->pattern_corners[2]); + glVertex2fv(marker->pattern_corners[3]); glEnd(); } @@ -698,10 +703,10 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra } /* only draw a pattern for the coarsest level */ glBegin(GL_LINE_LOOP); - glVertex2f(track->pat_min[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_max[1]); - glVertex2f(track->pat_min[0], track->pat_max[1]); + glVertex2fv(marker->pattern_corners[0]); + glVertex2fv(marker->pattern_corners[1]); + glVertex2fv(marker->pattern_corners[2]); + glVertex2fv(marker->pattern_corners[3]); glEnd(); glDisable(GL_LINE_STIPPLE); glPopMatrix(); @@ -717,6 +722,18 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, float marker_pos[2], int outline, int sel, int act, int width, int height) { +#if 1 + /* XXX: not re-implemented yet */ + (void) sc; + (void) track; + (void) marker; + (void) marker_pos; + (void) outline; + (void) sel; + (void) act; + (void) width; + (void) height; +#else float x, y, dx, dy, patdx, patdy, searchdx, searchdy, tdx, tdy; int tiny = sc->flag & SC_SHOW_TINY_MARKER; float col[3], scol[3], px[2]; @@ -845,6 +862,7 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo if (outline) glLineWidth(1.0f); +#endif } static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, @@ -881,8 +899,11 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra dy = track->search_min[1]; } else if (sc->flag & SC_SHOW_MARKER_PATTERN) { - dx = track->pat_min[0]; - dy = track->pat_min[1]; + float pat_min[2], pat_max[2]; + + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + dx = pat_min[0]; + dy = pat_min[1]; } pos[0] = (marker_pos[0] + dx) * width; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index a85d2352fbb..d2bff340b97 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -440,7 +440,8 @@ static void clip_operatortypes(void) /* markers */ WM_operatortype_append(CLIP_OT_add_marker); - WM_operatortype_append(CLIP_OT_slide_marker); + /* XXX: need porting! */ + //WM_operatortype_append(CLIP_OT_slide_marker); WM_operatortype_append(CLIP_OT_delete_track); WM_operatortype_append(CLIP_OT_delete_marker); @@ -614,7 +615,8 @@ static void clip_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CLIP_OT_delete_marker", DELKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "CLIP_OT_delete_marker", XKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "CLIP_OT_slide_marker", LEFTMOUSE, KM_PRESS, 0, 0); + /* XXX: need porting */ + //WM_keymap_add_item(keymap, "CLIP_OT_slide_marker", LEFTMOUSE, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "CLIP_OT_disable_markers", DKEY, KM_PRESS, KM_SHIFT, 0); RNA_enum_set(kmi->ptr, "action", 2); /* toggle */ diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index fc93bcc0409..cf88a59f705 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -78,6 +78,8 @@ #include "clip_intern.h" // own include +static float dist_to_crns(float co[2], float pos[2], float crns[4][2]); + /********************** add marker operator *********************/ static void add_marker(SpaceClip *sc, float x, float y) @@ -245,6 +247,8 @@ void CLIP_OT_delete_marker(wmOperatorType *ot) } /********************** slide marker operator *********************/ +/* XXX: need porting! */ +#if 0 #define SLIDE_ACTION_POS 0 #define SLIDE_ACTION_SIZE 1 @@ -646,6 +650,8 @@ void CLIP_OT_slide_marker(wmOperatorType *ot) "Offset", "Offset in floating point units, 1.0 is the width and height of the image", -FLT_MAX, FLT_MAX); } +#endif + /********************** mouse select operator *********************/ static int mouse_on_side(float co[2], float x1, float y1, float x2, float y2, float epsx, float epsy) @@ -668,18 +674,28 @@ static int mouse_on_rect(float co[2], float pos[2], float min[2], float max[2], mouse_on_side(co, pos[0] + max[0], pos[1] + min[1], pos[0] + max[0], pos[1] + max[1], epsx, epsy); } +static int mouse_on_crns(float co[2], float pos[2], float crns[4][2], float epsx, float epsy) +{ + float dist = dist_to_crns(co, pos, crns); + + return dist < MAX2(epsx, epsy); +} + static int track_mouse_area(SpaceClip *sc, float co[2], MovieTrackingTrack *track) { MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr); + float pat_min[2], pat_max[2]; float epsx, epsy; int width, height; ED_space_clip_size(sc, &width, &height); - epsx = MIN4(track->pat_min[0] - track->search_min[0], track->search_max[0] - track->pat_max[0], - fabsf(track->pat_min[0]), fabsf(track->pat_max[0])) / 2; - epsy = MIN4(track->pat_min[1] - track->search_min[1], track->search_max[1] - track->pat_max[1], - fabsf(track->pat_min[1]), fabsf(track->pat_max[1])) / 2; + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + epsx = MIN4(pat_min[0] - track->search_min[0], track->search_max[0] - pat_max[0], + fabsf(pat_min[0]), fabsf(pat_max[0])) / 2; + epsy = MIN4(pat_min[1] - track->search_min[1], track->search_max[1] - pat_max[1], + fabsf(pat_min[1]), fabsf(pat_max[1])) / 2; epsx = MAX2(epsx, 2.0f / width); epsy = MAX2(epsy, 2.0f / height); @@ -691,7 +707,7 @@ static int track_mouse_area(SpaceClip *sc, float co[2], MovieTrackingTrack *trac if ((marker->flag & MARKER_DISABLED) == 0) { if (sc->flag & SC_SHOW_MARKER_PATTERN) - if (mouse_on_rect(co, marker->pos, track->pat_min, track->pat_max, epsx, epsy)) + if (mouse_on_crns(co, marker->pos, marker->pattern_corners, epsx, epsy)) return TRACK_AREA_PAT; epsx = 12.0f / width; @@ -722,6 +738,21 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2]) return MIN4(d1, d2, d3, d4); } +static float dist_to_crns(float co[2], float pos[2], float crns[4][2]) +{ + float d1, d2, d3, d4; + float p[2] = {co[0] - pos[0], co[1] - pos[1]}; + float *v1 = crns[0], *v2 = crns[1], + *v3 = crns[2], *v4 = crns[3]; + + d1 = dist_to_line_segment_v2(p, v1, v2); + d2 = dist_to_line_segment_v2(p, v2, v3); + d3 = dist_to_line_segment_v2(p, v3, v4); + d4 = dist_to_line_segment_v2(p, v4, v1); + + return MIN4(d1, d2, d3, d4); +} + static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2]) { MovieTrackingTrack *track = NULL, *cur; @@ -736,11 +767,11 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbas /* distance to marker point */ d1 = sqrtf((co[0] - marker->pos[0] - cur->offset[0]) * (co[0] - marker->pos[0] - cur->offset[0]) + - (co[1] - marker->pos[1] - cur->offset[1]) * (co[1] - marker->pos[1] - cur->offset[1])); + (co[1] - marker->pos[1] - cur->offset[1]) * (co[1] - marker->pos[1] - cur->offset[1])); /* distance to pattern boundbox */ if (sc->flag & SC_SHOW_MARKER_PATTERN) - d2 = dist_to_rect(co, marker->pos, cur->pat_min, cur->pat_max); + d2 = dist_to_crns(co, marker->pos, marker->pattern_corners); /* distance to search boundbox */ if (sc->flag & SC_SHOW_MARKER_SEARCH && TRACK_VIEW_SELECTED(sc, cur)) @@ -822,6 +853,8 @@ static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) int extend = RNA_boolean_get(op->ptr, "extend"); if (!extend) { +#if 0 + /* XXX: need porting */ SlideMarkerData *slidedata = slide_marker_customdata(C, event); if (slidedata) { @@ -836,6 +869,7 @@ static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_PASS_THROUGH; } +#endif } ED_clip_mouse_pos(C, event, co); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 661f6ba7842..7949ecd5d19 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5420,8 +5420,10 @@ static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d, markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, marker->pos, NULL, NULL); if (track->pat_flag & SELECT) { - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, track->pat_min, marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, track->pat_max, marker->pos, NULL); + markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[0], marker->pos, NULL); + markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[1], marker->pos, NULL); + markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[2], marker->pos, NULL); + markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[3], marker->pos, NULL); } if (track->search_flag & SELECT) { @@ -5468,7 +5470,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) t->total++; if (track->pat_flag & SELECT) - t->total+= 2; + t->total+= 4; if (track->search_flag & SELECT) t->total+= 2; @@ -5507,9 +5509,9 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) } if (track->pat_flag & SELECT) { - td += 2; - td2d += 2; - tdt +=2; + td += 4; + td2d += 4; + tdt += 4; } } diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 6bf059c7ecb..1e7552f918f 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -35,6 +35,7 @@ #ifndef __DNA_TRACKING_TYPES_H__ #define __DNA_TRACKING_TYPES_H__ +#include "DNA_defs.h" #include "DNA_listBase.h" /* match-moving data */ @@ -68,6 +69,20 @@ typedef struct MovieTrackingCamera { typedef struct MovieTrackingMarker { float pos[2]; /* 2d position of marker on frame (in unified 0..1 space) */ + + /* corners of pattern in the following order: + * + * Y + * ^ + * | (3) --- (2) + * | | | + * | | | + * | | | + * | (0) --- (1) + * +-------------> X + */ + float pattern_corners[4][2]; + int framenr; /* number of frame marker is associated with */ int flag; /* Marker's flag (alive, ...) */ } MovieTrackingMarker; @@ -78,8 +93,13 @@ typedef struct MovieTrackingTrack { char name[64]; /* MAX_NAME */ /* ** setings ** */ - float pat_min[2], pat_max[2]; /* positions of left-bottom and right-top corners of pattern (in unified 0..1 space) */ - float search_min[2], search_max[2]; /* positions of left-bottom and right-top corners of search area (in unified 0..1 space) */ + + /* positions of left-bottom and right-top corners of pattern (in unified 0..1 space) */ + float pat_min[2], pat_max[2] DNA_DEPRECATED; + + /* positions of left-bottom and right-top corners of search area (in unified 0..1 space) */ + float search_min[2], search_max[2]; + float offset[2]; /* offset to "parenting" point */ /* ** track ** */ From 04d26bf44c4f2c5eb86aee117d818479d92f790b Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Mon, 14 May 2012 12:15:38 +0000 Subject: [PATCH 037/183] "Efficient Second-order Minimization" for the planar tracker This implements the "Efficient Second-order Minimization" scheme, as supported by the existing translation tracker. This increases the amount of per-iteration work, but decreases the number of iterations required to converge and also increases the size of the basin of attraction for the optimization. --- .../libmv/tracking/esm_region_tracker.cc | 1 + extern/libmv/libmv/tracking/track_region.cc | 99 ++++++++++++------- extern/libmv/libmv/tracking/track_region.h | 3 + 3 files changed, 67 insertions(+), 36 deletions(-) diff --git a/extern/libmv/libmv/tracking/esm_region_tracker.cc b/extern/libmv/libmv/tracking/esm_region_tracker.cc index 2491b158154..e6d0b9830f4 100644 --- a/extern/libmv/libmv/tracking/esm_region_tracker.cc +++ b/extern/libmv/libmv/tracking/esm_region_tracker.cc @@ -102,6 +102,7 @@ bool EsmRegionTracker::Track(const FloatImage &image1, options.num_samples_y = 2 * half_window_size + 1; options.max_iterations = 20; options.sigma = sigma; + options.use_esm = true; TrackRegionResult result; TrackRegion(image1, image2, xx1, yy1, options, xx2, yy2, &result); diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index 5a46c66cd3c..0bb8ae221b1 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -63,33 +63,32 @@ bool AllInBounds(const FloatImage &image, // supported, the sample function must be inside a template-specialized class // with a non-templated static member. -// The "AutoDiffImage::Sample()" function allows sampling an image at an x, y +// The "AutoDiff::Sample()" function allows sampling an image at an x, y // position such that if x and y are jets, then the derivative information is // correctly propagated. // Empty default template. template -struct AutoDiffImage { +struct AutoDiff { + // Sample only the image when the coordinates are scalars. static T Sample(const FloatImage &image_and_gradient, const T &x, const T &y) { - return 0.0; - } -}; - -// Sample only the image when the coordinates are scalars. -template<> -struct AutoDiffImage { - static double Sample(const FloatImage &image_and_gradient, - const double& x, const double& y) { return SampleLinear(image_and_gradient, y, x, 0); } + + static void SetScalarPart(double scalar, T *value) { + *value = scalar; + } + static void ScaleDerivative(double scale_by, T *value) { + // For double, there is no derivative to scale. + } }; // Sample the image and gradient when the coordinates are jets, applying the // jacobian appropriately to propagate the derivatives from the coordinates. template<> template -struct AutoDiffImage > { +struct AutoDiff > { static ceres::Jet Sample(const FloatImage &image_and_gradient, const ceres::Jet &x, const ceres::Jet &y) { @@ -116,6 +115,13 @@ struct AutoDiffImage > { jet_s.v = Matrix(dsdx, dsdy) * dxydz; return jet_s; } + + static void SetScalarPart(double scalar, ceres::Jet *value) { + value->a = scalar; + } + static void ScaleDerivative(double scale_by, ceres::Jet *value) { + value->v *= scale_by; + } }; template @@ -151,18 +157,16 @@ class BoundaryCheckingCallback : public ceres::IterationCallback { template class WarpCostFunctor { public: - WarpCostFunctor(const FloatImage &image_and_gradient1, + WarpCostFunctor(const TrackRegionOptions &options, + const FloatImage &image_and_gradient1, const FloatImage &image_and_gradient2, const Mat3 &canonical_to_image1, - const Warp &warp, - int num_samples_x, - int num_samples_y) - : image_and_gradient1_(image_and_gradient1), + const Warp &warp) + : options_(options), + image_and_gradient1_(image_and_gradient1), image_and_gradient2_(image_and_gradient2), canonical_to_image1_(canonical_to_image1), - warp_(warp), - num_samples_x_(num_samples_x), - num_samples_y_(num_samples_y) {} + warp_(warp) {} template bool operator()(const T *warp_parameters, T *residuals) const { @@ -171,8 +175,8 @@ class WarpCostFunctor { } int cursor = 0; - for (int r = 0; r < num_samples_y_; ++r) { - for (int c = 0; c < num_samples_x_; ++c) { + for (int r = 0; r < options_.num_samples_y; ++r) { + for (int c = 0; c < options_.num_samples_x; ++c) { // Compute the location of the source pixel (via homography). Vec3 image1_position = canonical_to_image1_ * Vec3(c, r, 1); image1_position /= image1_position(2); @@ -185,28 +189,52 @@ class WarpCostFunctor { &image2_position[0], &image2_position[1]); - // Sample the source and destination. - double src_sample = AutoDiffImage::Sample(image_and_gradient1_, - image1_position[0], - image1_position[1]); - T dst_sample = AutoDiffImage::Sample(image_and_gradient2_, - image2_position[0], - image2_position[1]); + + // Sample the destination, propagating derivatives. + T dst_sample = AutoDiff::Sample(image_and_gradient2_, + image2_position[0], + image2_position[1]); + + // Sample the source. This is made complicated by ESM mode. + T src_sample; + if (options_.use_esm) { + // In ESM mode, the derivative of the source is also taken into + // account. This changes the linearization in a way that causes + // better convergence. Copy the derivative of the warp parameters + // onto the jets for the image1 position. This is the ESM hack. + T image1_position_x = image2_position[0]; + T image1_position_y = image2_position[1]; + AutoDiff::SetScalarPart(image1_position[0], &image1_position_x); + AutoDiff::SetScalarPart(image1_position[1], &image1_position_y); + src_sample = AutoDiff::Sample(image_and_gradient1_, + image1_position_x, + image1_position_y); + + // The jacobians for these should be averaged. Due to the subtraction + // below, flip the sign of the src derivative so that the effect + // after subtraction of the jets is that they are averaged. + AutoDiff::ScaleDerivative(-0.5, &src_sample); + AutoDiff::ScaleDerivative(0.5, &dst_sample); + } else { + // This is the traditional, forward-mode KLT solution. + src_sample = T(AutoDiff::Sample(image_and_gradient1_, + image1_position[0], + image1_position[1])); + } // The difference is the error. - residuals[cursor++] = T(src_sample) - dst_sample; + residuals[cursor++] = src_sample - dst_sample; } } return true; } private: + const TrackRegionOptions &options_; const FloatImage &image_and_gradient1_; const FloatImage &image_and_gradient2_; const Mat3 &canonical_to_image1_; const Warp &warp_; - int num_samples_x_; - int num_samples_y_; }; // Compute the warp from rectangular coordinates, where one corner is the @@ -570,12 +598,11 @@ void TemplatedTrackRegion(const FloatImage &image1, // Construct the warp cost function. AutoDiffCostFunction takes ownership. WarpCostFunctor *cost_function = - new WarpCostFunctor(image_and_gradient1, + new WarpCostFunctor(options, + image_and_gradient1, image_and_gradient2, canonical_homography, - warp, - options.num_samples_x, - options.num_samples_y); + warp); // Construct the problem with a single residual. ceres::Problem::Options problem_options; diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h index ca783c32a75..7c937c04794 100644 --- a/extern/libmv/libmv/tracking/track_region.h +++ b/extern/libmv/libmv/tracking/track_region.h @@ -47,6 +47,9 @@ struct TrackRegionOptions { double minimum_correlation; int max_iterations; + + // Use the "Efficient Second-order Minimization" scheme. This increases + // convergence speed at the cost of more per-iteration work. bool use_esm; double sigma; From e9d520f482561cba0fe01ffa44b5f6eb97ee0276 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Mon, 14 May 2012 13:46:38 +0000 Subject: [PATCH 038/183] Refactor byte/float RGBA to grayscale conversion in tracking.c This is the first in a series of tracking.c refactorings to disentangle functionality that is sprinkled across unrelated functions. --- source/blender/blenkernel/intern/tracking.c | 45 ++++++++++++--------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index e8168da45fb..43188cc7877 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1264,11 +1264,29 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov } #ifdef WITH_LIBMV + +/* Convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ +static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue) { + int i; + for (i = 0; i < num_pixels; ++i) { + const float *pixel = rgba + 4 * i; + gray[i] = weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]; + } +} + +static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue) { + int i; + for (i = 0; i < num_pixels; ++i) { + const unsigned char *pixel = rgba + i * 4; + *gray++ = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f; + } +} + static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, int *width_r, int *height_r, float pos[2], int origin[2]) { ImBuf *tmpibuf; - float *pixels, *fp; + float *gray_pixels; int x, y, width, height; width = (track->search_max[0] - track->search_min[0]) * ibuf->x; @@ -1280,29 +1298,18 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT *width_r = width; *height_r = height; - fp = pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf"); - for (y = 0; y < (int)height; y++) { - for (x = 0; x < (int)width; x++) { - int pixel = tmpibuf->x * y + x; + gray_pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf"); - if (tmpibuf->rect_float) { - float *rrgbf = tmpibuf->rect_float + pixel * 4; - - *fp = 0.2126 * rrgbf[0] + 0.7152 * rrgbf[1] + 0.0722 * rrgbf[2]; - } - else { - unsigned char *rrgb = (unsigned char*)tmpibuf->rect + pixel * 4; - - *fp = (0.2126 * rrgb[0] + 0.7152 * rrgb[1] + 0.0722 * rrgb[2]) / 255.0f; - } - - fp++; - } + if (tmpibuf->rect_float) { + float_rgba_to_gray(tmpibuf->rect_float, gray_pixels, height * width, 0.2126f, 0.7152f, 0.0722f); + } + else { + uint8_rgba_to_float_gray((unsigned char *)tmpibuf->rect, gray_pixels, height * width, 0.2126f, 0.7152f, 0.0722f); } IMB_freeImBuf(tmpibuf); - return pixels; + return gray_pixels; } static unsigned char *get_ucharbuf(ImBuf *ibuf) From 255e9ce15ad775a9cfef0713d7f280a656f11367 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 May 2012 15:24:13 +0000 Subject: [PATCH 039/183] fix for glitch adding markers, when there are 2 splines, and the first spline wasnt active but _was_ selected, Ctrl+Click would use the non-active selected spline. now use the active spline when available. also no need to de-select when adding a new vertex inbetween 2 verts in a spline. --- source/blender/editors/mask/mask_ops.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index aee73205c99..56d8abb5836 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1197,7 +1197,10 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) MaskSplinePoint *new_point_array, *new_point; int point_index = point - spline->points; + /* adding _could_ deselect, for now don't */ +#if 0 toggle_selection_all(mask, SEL_DESELECT); +#endif new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); @@ -1225,13 +1228,21 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) /* **** add extrude vertex **** */ -static void finSelectedSplinePoint(MaskShape *shape, MaskSpline **spline, MaskSplinePoint **point) +static void finSelectedSplinePoint(MaskShape *shape, MaskSpline **spline, MaskSplinePoint **point, short check_active) { MaskSpline *cur_spline = shape->splines.first; *spline = NULL; *point = NULL; + if (check_active) { + if (shape->act_spline && shape->act_point) { + *spline = shape->act_spline; + *point = shape->act_point; + return; + } + } + while (cur_spline) { int i; @@ -1264,6 +1275,11 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) MaskSpline *spline; MaskSplinePoint *point, *new_point = NULL; + /* adding _could_ deselect, for now don't */ +#if 0 + toggle_selection_all(mask, SEL_DESELECT); +#endif + shape = BKE_mask_shape_active(mask); if (!shape) { @@ -1274,7 +1290,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) point = NULL; } else { - finSelectedSplinePoint(shape, &spline, &point); + finSelectedSplinePoint(shape, &spline, &point, TRUE); } if (!spline) { From 389ae7131664a2404fc3409f969f7ff9fb9171d0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 May 2012 15:59:53 +0000 Subject: [PATCH 040/183] when adding new points to mask - base when adding between 2 points use their handle types. - when extruding an existing point use its handle type. --- source/blender/editors/mask/mask_ops.c | 29 ++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 56d8abb5836..e4f6c2656e2 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1086,8 +1086,11 @@ void MASK_OT_select(wmOperatorType *ot) /******************** add vertex *********************/ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, - float point_co[2], float tangent[2]) + const float point_co[2], const float tangent[2], + MaskSplinePoint *reference_point, const short reference_adjacent) { + MaskSplinePoint *prev_point = NULL; + MaskSplinePoint *next_point = NULL; BezTriple *bezt; int width, height; float co[3]; @@ -1103,6 +1106,21 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask bezt->h1 = bezt->h2 = HD_ALIGN; + if (reference_point) { + bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1); + } + else if (reference_adjacent) { + if (spline->tot_point != 1) { + int index = (int)(new_point - spline->points); + prev_point = &spline->points[(index - 1) % spline->tot_point]; + next_point = &spline->points[(index + 1) % spline->tot_point]; + + bezt->h1 = bezt->h2 = MAX2(prev_point->bezt.h2, next_point->bezt.h1); + + /* note, we may want to copy other attributes later, radius? pressure? color? */ + } + } + copy_v3_v3(bezt->vec[0], co); copy_v3_v3(bezt->vec[1], co); copy_v3_v3(bezt->vec[2], co); @@ -1214,7 +1232,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) new_point = &new_point_array[point_index + 1]; - setup_vertex_point(C, mask, spline, new_point, co, tangent); + setup_vertex_point(C, mask, spline, new_point, co, tangent, NULL, TRUE); shape->act_point = new_point; @@ -1273,7 +1291,8 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) { MaskShape *shape; MaskSpline *spline; - MaskSplinePoint *point, *new_point = NULL; + MaskSplinePoint *point; + MaskSplinePoint *new_point = NULL, *ref_point = NULL; /* adding _could_ deselect, for now don't */ #if 0 @@ -1312,6 +1331,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) spline->tot_point++; new_point = &spline->points[spline->tot_point - 1]; + ref_point = &spline->points[spline->tot_point - 2]; } else if (point == &spline->points[0]) { MASKPOINT_DESEL(point); @@ -1322,6 +1342,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) spline->tot_point++; new_point = &spline->points[0]; + ref_point = &spline->points[1]; } else { spline = BKE_mask_spline_add(shape); @@ -1332,7 +1353,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) shape->act_point = new_point; - setup_vertex_point(C, mask, spline, new_point, co, NULL); + setup_vertex_point(C, mask, spline, new_point, co, NULL, ref_point, FALSE); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return TRUE; From c62077ce66ca40b564176e5fb6f8b1c1907626c4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 14 May 2012 17:23:37 +0000 Subject: [PATCH 041/183] Per-track grease pencil data blocks Added support of tracks to have their own grease pencil datablock. This is controllable by Clip/Track toggle in Grease Pencil panel in Clip Editor. This toggle shows whether grease pencil stroke should go to movie clip's datablock or to active track. As soon as this toggle is switched to Track, all further strokes would be added to active track and only strokes which belongs to active track would be displayed on the screen. This strokes would be relative to track's position, which means if one made some strokes to track and started moving it, stokes would be moved together with track. Different tracks might share the same grease pencil datablock. Also hide draw modes which are not supported by space clip. Initial idea why tracks should have grease pencil datablocks was to support easy mask creation for tracking. This seemed fastest and easiest way to achieve mask editing for tracks. To get mask for specified track there's function BKE_tracking_track_mask_get which requires MovieTracking structure, track for which mask is creating and also width and height of current overall frame. it'll return ImBuf with mask (probably it's more like overkill, because internally it works with single-channel value buffer and probably that's one should be passing to libmv). Probably hacking grease pencil in such way is not ideal solution, but that part of code might be cleaned up further and it seems to be straightforward to use grease pencil for such a purpose. Note: this is commit to tomato branch, not to trunk. --- source/blender/blenkernel/BKE_tracking.h | 1 + source/blender/blenkernel/CMakeLists.txt | 1 + source/blender/blenkernel/SConscript | 1 + source/blender/blenkernel/intern/tracking.c | 102 ++++++++++++++++++ source/blender/blenloader/intern/readfile.c | 7 +- source/blender/blenloader/intern/writefile.c | 2 +- .../blender/editors/gpencil/gpencil_buttons.c | 29 +++-- source/blender/editors/gpencil/gpencil_edit.c | 21 +++- .../blender/editors/gpencil/gpencil_paint.c | 10 ++ source/blender/editors/space_clip/clip_draw.c | 47 ++++++-- .../blender/editors/space_clip/space_clip.c | 7 +- source/blender/makesdna/DNA_space_types.h | 9 +- source/blender/makesdna/DNA_tracking_types.h | 3 + .../blender/makesrna/intern/rna_movieclip.c | 1 + source/blender/makesrna/intern/rna_space.c | 13 +++ source/blender/makesrna/intern/rna_tracking.c | 8 ++ 16 files changed, 238 insertions(+), 24 deletions(-) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 84beca4fd96..f8869bfc74c 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -77,6 +77,7 @@ struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTra struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int margin, int anchored, float pos[2], int origin[2]); +struct ImBuf *BKE_tracking_track_mask_get(struct MovieTracking *tracking, struct MovieTrackingTrack *track, int width, int height); void BKE_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 61461044fa7..521cabe31e5 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -43,6 +43,7 @@ set(INC ../../../intern/memutil ../../../intern/mikktspace ../../../intern/opennl/extern + ../../../intern/raskter # XXX - BAD LEVEL CALL WM_api.h ../windowmanager diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index ee9e6bc7739..64544adb26d 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -17,6 +17,7 @@ incs += ' #/intern/smoke/extern' incs += ' #/intern/mikktspace' incs += ' #/intern/audaspace/intern' incs += ' #/intern/ffmpeg' +incs += ' #/intern/raskter' incs += ' ' + env['BF_OPENGL_INC'] incs += ' ' + env['BF_ZLIB_INC'] diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 43188cc7877..2299860b5ae 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -59,6 +59,8 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "raskter.h" + #ifdef WITH_LIBMV # include "libmv-capi.h" #else @@ -1263,6 +1265,106 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov return get_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin); } +static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track) +{ + bGPDlayer *layer; + + if (!track->gpd) + return NULL; + + layer = track->gpd->layers.first; + + while (layer) { + if (layer->flag & GP_LAYER_ACTIVE) + return layer; + + layer = layer->next; + } + + return NULL; +} + +static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTrackingTrack *track, + bGPDlayer *layer, ImBuf *ibuf, int width, int height) +{ + bGPDframe *frame = layer->frames.first; + float *mask; + int x, y; + float aspy = 1.0f / tracking->camera.pixel_aspect; + + mask = MEM_callocN(ibuf->x * ibuf->y * sizeof(float), "track mask"); + + while (frame) { + bGPDstroke *stroke = frame->strokes.first; + + while (stroke) { + bGPDspoint *stroke_points = stroke->points; + float *mask_points, *fp; + int i; + + if (stroke->flag & GP_STROKE_2DSPACE) { + fp = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(float), + "track mask rasterization points"); + + for (i = 0; i < stroke->totpoints; i++, fp += 2) { + fp[0] = stroke_points[i].x * width / ibuf->x - track->search_min[0]; + fp[1] = stroke_points[i].y * height * aspy / ibuf->x - track->search_min[1]; + } + + PLX_raskterize(mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y); + + MEM_freeN(mask_points); + } + + stroke = stroke->next; + } + + frame = frame->next; + } + + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + float *pixel = &ibuf->rect_float[4 * (y * ibuf->x + x)]; + float val = mask[y * ibuf->x + x]; + + pixel[0] = val; + pixel[1] = val; + pixel[2] = val; + pixel[3] = 1.0f; + } + } + + MEM_freeN(mask); + + IMB_rect_from_float(ibuf); +} + +ImBuf *BKE_tracking_track_mask_get(MovieTracking *tracking, MovieTrackingTrack *track, int width, int height) +{ + ImBuf *ibuf; + bGPDlayer *layer = track_mask_gpencil_layer_get(track); + int mask_width, mask_height; + + /* XXX: currently copied from get_area_ibuf */ + mask_width = (track->search_max[0] - track->search_min[0]) * width; + mask_height = (track->search_max[1] - track->search_min[1]) * height; + + mask_width = mask_width | 1; + mask_height = mask_height | 1; + + ibuf = IMB_allocImBuf(mask_width, mask_height, 32, IB_rect | IB_rectfloat); + + if (layer) { + track_mask_gpencil_layer_rasterize(tracking, track, layer, ibuf, width, height); + } + else { + float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + IMB_rectfill(ibuf, white); + } + + return ibuf; +} + #ifdef WITH_LIBMV /* Convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 79a09ab6c23..a3ea1f3c841 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6198,7 +6198,7 @@ static void direct_link_movieReconstruction(FileData *fd, MovieTrackingReconstru reconstruction->cameras= newdataadr(fd, reconstruction->cameras); } -static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase) +static void direct_link_movieTracks(FileData *fd, MovieClip *clip, ListBase *tracksbase) { MovieTrackingTrack *track; @@ -6207,6 +6207,7 @@ static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase) track= tracksbase->first; while (track) { track->markers= newdataadr(fd, track->markers); + track->gpd= newlibadr_us(fd, clip->id.lib, track->gpd); track= track->next; } @@ -6225,7 +6226,7 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) if (fd->movieclipmap) clip->tracking.camera.intrinsics= newmclipadr(fd, clip->tracking.camera.intrinsics); else clip->tracking.camera.intrinsics= NULL; - direct_link_movieTracks(fd, &tracking->tracks); + direct_link_movieTracks(fd, clip, &tracking->tracks); direct_link_movieReconstruction(fd, &tracking->reconstruction); clip->tracking.act_track= newdataadr(fd, clip->tracking.act_track); @@ -6245,7 +6246,7 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) object= tracking->objects.first; while (object) { - direct_link_movieTracks(fd, &object->tracks); + direct_link_movieTracks(fd, clip, &object->tracks); direct_link_movieReconstruction(fd, &object->reconstruction); object= object->next; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 93d7f9bdc2f..539b19c5561 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2886,6 +2886,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil write_windowmanagers(wd, &mainvar->wm); write_screens (wd, &mainvar->screen); } + write_gpencils (wd, &mainvar->gpencil); write_movieclips (wd, &mainvar->movieclip); write_masks (wd, &mainvar->mask); write_scenes (wd, &mainvar->scene); @@ -2912,7 +2913,6 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil write_nodetrees(wd, &mainvar->nodetree); write_brushes (wd, &mainvar->brush); write_scripts (wd, &mainvar->script); - write_gpencils (wd, &mainvar->gpencil); write_libraries(wd, mainvar->next); if (write_user_block) { diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c index 3a7e806c2ed..b59f3756819 100644 --- a/source/blender/editors/gpencil/gpencil_buttons.c +++ b/source/blender/editors/gpencil/gpencil_buttons.c @@ -40,6 +40,7 @@ #include "DNA_gpencil_types.h" #include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "BKE_context.h" #include "BKE_global.h" @@ -236,6 +237,7 @@ static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, Poin PointerRNA gpd_ptr; bGPDlayer *gpl; uiLayout *col, *row; + SpaceClip *sc= CTX_wm_space_clip(C); short v3d_stroke_opts = STROKE_OPTS_NORMAL; const short is_v3d = CTX_wm_view3d(C) != NULL; @@ -244,6 +246,16 @@ static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, Poin /* draw gpd settings first ------------------------------------- */ col = uiLayoutColumn(layout, 0); + + if (sc) { + bScreen *screen = CTX_wm_screen(C); + PointerRNA sc_ptr; + + RNA_pointer_create(&screen->id, &RNA_SpaceClipEditor, sc, &sc_ptr); + row = uiLayoutRow(col, 1); + uiItemR(row, &sc_ptr, "grease_pencil_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + } + /* current Grease Pencil block */ /* TODO: show some info about who owns this? */ uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink"); @@ -281,14 +293,17 @@ static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, Poin row = uiLayoutRow(col, 1); uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, ICON_NONE); uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, ICON_NONE); - row = uiLayoutRow(col, 1); - uiLayoutSetActive(row, v3d_stroke_opts); - uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NONE); - uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NONE); - row = uiLayoutRow(col, 0); - uiLayoutSetActive(row, v3d_stroke_opts == STROKE_OPTS_V3D_ON); - uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NONE); + if (sc == NULL) { + row = uiLayoutRow(col, 1); + uiLayoutSetActive(row, v3d_stroke_opts); + uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NONE); + uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NONE); + + row = uiLayoutRow(col, 0); + uiLayoutSetActive(row, v3d_stroke_opts == STROKE_OPTS_V3D_ON); + uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NONE); + } } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 9250d48a20c..71cbabe9114 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -57,6 +57,7 @@ #include "BKE_library.h" #include "BKE_object.h" #include "BKE_report.h" +#include "BKE_tracking.h" #include "WM_api.h" @@ -144,9 +145,23 @@ bGPdata **gpencil_data_get_pointers(bContext *C, PointerRNA *ptr) MovieClip *clip = ED_space_clip(sc); if (clip) { - /* for now, as long as there's a clip, default to using that in Clip Editor */ - if (ptr) RNA_id_pointer_create(&clip->id, ptr); - return &clip->gpd; + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + MovieTrackingTrack *track = BKE_tracking_active_track(&clip->tracking); + + if (!track) + return NULL; + + if (ptr) + RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr); + + return &track->gpd; + } + else { + if (ptr) + RNA_id_pointer_create(&clip->id, ptr); + + return &clip->gpd; + } } } break; diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 5c23aba9024..4021b82b2df 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -44,6 +44,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_report.h" +#include "BKE_tracking.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -1125,6 +1126,15 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) p->custom_color[1] = 0.0f; p->custom_color[2] = 0.5f; p->custom_color[3] = 0.9f; + + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + int framenr = sc->user.framenr; + MovieTrackingTrack *track = BKE_tracking_active_track(&sc->clip->tracking); + MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); + + p->imat[3][0] -= marker->pos[0]; + p->imat[3][1] -= marker->pos[1]; + } } break; diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 8a9d9313a6c..27a4532c89f 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1196,8 +1196,10 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, int i, j, a; float pos[2], tpos[2], grid[11][11][2]; MovieTracking *tracking = &clip->tracking; + bGPdata *gpd = NULL; float aspy = 1.0f / tracking->camera.pixel_aspect; float dx = (float)width / n, dy = (float)height / n * aspy; + float offsx = 0.0f, offsy = 0.0f; if (sc->mode != SC_MODE_DISTORTION) return; @@ -1305,8 +1307,27 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, } } - if (sc->flag & SC_MANUAL_CALIBRATION && clip->gpd) { - bGPDlayer *layer = clip->gpd->layers.first; + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + MovieTrackingTrack *track = BKE_tracking_active_track(&sc->clip->tracking); + + if (track) { + int framenr = sc->user.framenr; + MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); + + offsx = marker->pos[0]; + offsy = marker->pos[1]; + + gpd = track->gpd; + } + + } + else { + gpd = clip->gpd; + } + + + if (sc->flag & SC_MANUAL_CALIBRATION) { + bGPDlayer *layer = gpd->layers.first; while (layer) { bGPDframe *frame = layer->frames.first; @@ -1331,11 +1352,11 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, float npos[2], dpos[2], len; int steps; - pos[0] = stroke->points[i].x * width; - pos[1] = stroke->points[i].y * height * aspy; + pos[0] = (stroke->points[i].x + offsx) * width; + pos[1] = (stroke->points[i].y + offsy) * height * aspy; - npos[0] = stroke->points[i + 1].x * width; - npos[1] = stroke->points[i + 1].y * height * aspy; + npos[0] = (stroke->points[i + 1].x + offsx) * width; + npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy; len = len_v2v2(pos, npos); steps = ceil(len / 5.0f); @@ -1360,7 +1381,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, } else if (stroke->totpoints == 1) { glBegin(GL_POINTS); - glVertex2f(stroke->points[0].x, stroke->points[0].y); + glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy); glEnd(); } } @@ -1464,6 +1485,18 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d) if (ibuf) { glPushMatrix(); glMultMatrixf(sc->unistabmat); + + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + MovieTrackingTrack *track = BKE_tracking_active_track(&sc->clip->tracking); + + if (track) { + int framenr = sc->user.framenr; + MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); + + glTranslatef(marker->pos[0], marker->pos[1], 0.0f); + } + } + draw_gpencil_2dimage(C, ibuf); IMB_freeImBuf(ibuf); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 75c60ed5b60..2db563643a3 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -389,8 +389,11 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) } break; case NC_SCREEN: - if (wmn->data == ND_ANIMPLAY) { - ED_area_tag_redraw(sa); + switch (wmn->data) { + case ND_ANIMPLAY: + case ND_GPENCIL: + ED_area_tag_redraw(sa); + break; } break; case NC_SPACE: diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index a0528347658..640961f80f2 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -521,7 +521,10 @@ typedef struct SpaceClip { * defined when drawing and used for mouse position calculation */ /* movie postprocessing */ - int postproc_flag, pad2; + int postproc_flag; + + /* grease pencil */ + short gpencil_src, pad2; void *draw_context; @@ -935,6 +938,10 @@ enum { /* SpaceClip->dope_flag */ #define SC_DOPE_SORT_INVERSE 1 +/* SPaceClip->gpencil_src */ +#define SC_GPENCIL_SRC_CLIP 0 +#define SC_GPENCIL_SRC_TRACK 1 + /* space types, moved from DNA_screen_types.h */ /* Do NOT change order, append on end. types are hardcoded needed */ enum { diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 1e7552f918f..feb77c5c9ec 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -40,6 +40,7 @@ /* match-moving data */ +struct bGPdata; struct ImBuf; struct MovieReconstructedCamera; struct MovieTrackingCamera; @@ -127,6 +128,8 @@ typedef struct MovieTrackingTrack { /* ** SAD tracker settings ** */ float minimum_correlation; /* minimal correlation which is still treated as successful tracking */ + + struct bGPdata *gpd; /* grease-pencil data */ } MovieTrackingTrack; typedef struct MovieTrackingSettings { diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 2cbe6946485..13c11f6402f 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -284,6 +284,7 @@ static void rna_def_movieclip(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "GreasePencil"); RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this movie clip"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); } void RNA_def_movieclip(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 5f92071ded7..13d25c78d5d 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2980,6 +2980,12 @@ static void rna_def_space_clip(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem gpencil_source_items[] = { + {SC_GPENCIL_SRC_CLIP, "CLIP", 0, "Clip", "Show grease pencil datablock which belongs to movie clip"}, + {SC_GPENCIL_SRC_TRACK, "TRACK", 0, "Track", "Show grease pencil datablock which belongs to active track"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "SpaceClipEditor", "Space"); RNA_def_struct_sdna(srna, "SpaceClip"); RNA_def_struct_ui_text(srna, "Space Clip Editor", "Clip editor space data"); @@ -3166,6 +3172,13 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + /* grease pencil source */ + prop = RNA_def_property(srna, "grease_pencil_source", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "gpencil_src"); + RNA_def_property_enum_items(prop, gpencil_source_items); + RNA_def_property_ui_text(prop, "Grease Pencil Source", "Where the grease pencil comes from"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + /* ** dopesheet ** */ /* dopesheet sort */ diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 7a6753ad588..9f5dc75506b 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -1088,6 +1088,14 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "error"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Average Error", "Average error of re-projection"); + + /* grease pencil */ + prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "gpd"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "GreasePencil"); + RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this track"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); } static void rna_def_trackingStabilization(BlenderRNA *brna) From a673e70e7c9ffe27b28c1bcf4de9e8f4a65fc23e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 May 2012 19:41:27 +0000 Subject: [PATCH 042/183] fix for odd mask curve handle calculation - reuses auto handle calculation - keeps handle length relate to surrounding handles todo - only works well when cyclic is off - isnt aspect aware (looks like other tools are not aspect aware too) --- source/blender/blenkernel/BKE_mask.h | 6 ++ source/blender/blenkernel/intern/mask.c | 137 +++++++++++++++++++----- source/blender/editors/mask/mask_ops.c | 12 ++- 3 files changed, 126 insertions(+), 29 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 31a872b5056..be14229b323 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -82,6 +82,12 @@ void BKE_mask_unlink(struct Main *bmain, struct Mask *mask); void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime); void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene); void BKE_mask_parent_init(struct MaskParent *parent); +void BKE_mask_calc_handle_point(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); +void BKE_mask_calc_handle_point_auto(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, + const short do_length_match); +void BKE_mask_get_handle_point_adjacent(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, + struct MaskSplinePoint **r_point_prev, struct MaskSplinePoint **r_point_next); +void BKE_mask_calc_handles(struct Mask *mask); #define MASKPOINT_ISSEL(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) #define MASKPOINT_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 55dab26b841..3f5a5783950 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -794,42 +794,125 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev } } -void BKE_mask_calc_handles(Mask *mask) +void BKE_mask_get_handle_point_adjacent(Mask *UNUSED(mask), MaskSpline *spline, MaskSplinePoint *point, + MaskSplinePoint **r_point_prev, MaskSplinePoint **r_point_next) { - MaskShape *shape = mask->shapes.first; + MaskSplinePoint *prev_point, *next_point; + int i = (int)(point - spline->points); - while (shape) { - MaskSpline *spline = shape->splines.first; - int i; + BLI_assert(i >= i && i < spline->tot_point); - while (spline) { - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - MaskSplinePoint *prev_point, *next_point; + if (i == 0) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + prev_point = &spline->points[spline->tot_point - 1]; + } + else { + prev_point = NULL; + } + } + else { + prev_point = point - 1; + } - if (i == 0) { - if (spline->flag & MASK_SPLINE_CYCLIC) - prev_point = &spline->points[spline->tot_point - 1]; - else - prev_point = NULL; - } - else prev_point = point - 1; + if (i == spline->tot_point - 1) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + next_point = &spline->points[0]; + } + else { + next_point = NULL; + } + } + else { + next_point = point + 1; + } - if (i == spline->tot_point - 1) { - if (spline->flag & MASK_SPLINE_CYCLIC) - next_point = &spline->points[0]; - else - next_point = NULL; - } - else next_point = point + 1; + *r_point_prev = prev_point; + *r_point_next = next_point; +} - mask_calc_point_handle(point, prev_point, next_point); - } +void BKE_mask_calc_handle_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) +{ + MaskSplinePoint *prev_point, *next_point; - spline = spline->next; + BKE_mask_get_handle_point_adjacent(mask, spline, point, + &prev_point, &next_point); + + mask_calc_point_handle(point, prev_point, next_point); +} + +static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dist) +{ + if (!equals_v2v2(v2, v1)) { + float nor[2]; + + sub_v2_v2v2(nor, v1, v2); + normalize_v2(nor); + madd_v2_v2v2fl(v1, v2, nor, dist); + } +} + +/** + * \brief Resets auto handles even for non-auto bezier points + * + * Useful for giving sane defaults. + */ +void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, + const short do_length_match) +{ + MaskSplinePoint *prev_point, *next_point; + + const char h_back[2] = {point->bezt.h1, point->bezt.h2}; + + BKE_mask_get_handle_point_adjacent(mask, spline, point, + &prev_point, &next_point); + + point->bezt.h1 = HD_AUTO; + point->bezt.h2 = HD_AUTO; + mask_calc_point_handle(point, prev_point, next_point); + + point->bezt.h1 = h_back[0]; + point->bezt.h2 = h_back[1]; + mask_calc_point_handle(point, prev_point, next_point); + + /* TODO! - make this aspect aware! */ + /* TODO! - not working right with cyclic curves, need to investigate! */ + if (do_length_match) { + int length_tot = 0; + float length_average = 0.0f; + + if (prev_point) { + length_average += len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]); + length_tot++; } - shape = shape->next; + if (next_point) { + length_average += len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]); + length_tot++; + } + + if (length_tot) { + length_average /= (float)length_tot; + + enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); + enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + } + } +} + +void BKE_mask_calc_handles(Mask *mask) +{ + MaskShape *shape; + + for (shape = mask->shapes.first; shape; shape = shape->next) { + MaskSpline *spline; + + for (spline = shape->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + BKE_mask_calc_handle_point(mask, spline, &spline->points[i]); + } + } } } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index e4f6c2656e2..661030cb382 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -480,9 +480,9 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], if (feather_points) MEM_freeN(feather_points); - } - MEM_freeN(diff_points); + MEM_freeN(diff_points); + } } spline = spline->next; @@ -1148,6 +1148,9 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask add_v2_v2(bezt->vec[2], vec); } else { + + /* calculating auto handles works much nicer */ +#if 0 /* next points are aligning in the direction of previous/next point */ MaskSplinePoint *point; float v1[2], v2[2], vec[2]; @@ -1192,6 +1195,11 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask add_v2_v2(bezt->vec[0], vec); sub_v2_v2(bezt->vec[2], vec); +#else + BKE_mask_calc_handle_point_auto(mask, spline, new_point, TRUE); + +#endif + } BKE_mask_parent_init(&new_point->parent); From 432ff1a17e77e80067bd29a7ec92ff7ed7e19620 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 15 May 2012 10:55:26 +0000 Subject: [PATCH 043/183] Tomato: support of corners sliding for mouse sliding operator This commits re-enables mouse sliding operator which behaves in the same way as it used to for search area and marker position, but for pattern it's now using individual corners. This allows to define affine transformation which later would be used by tracker algorithm. For non-affine tracking code is also ported but currently it's hardcoded to use affine transformation. When real affine trackers and RNA/DNA changes would be commited, easy to switch sliding operator to old-school behavior for non-affine patterns. --- source/blender/editors/space_clip/clip_draw.c | 162 +++++++------ .../blender/editors/space_clip/space_clip.c | 6 +- .../blender/editors/space_clip/tracking_ops.c | 212 ++++++++++++++---- 3 files changed, 252 insertions(+), 128 deletions(-) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 27a4532c89f..7fd4f1bafae 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -719,24 +719,69 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra glPopMatrix(); } +static float get_shortest_pattern_side(MovieTrackingMarker *marker) +{ + int i, next; + float len = FLT_MAX; + + for (i = 0; i < 4; i++) { + float cur_len; + + next = (i + 1) % 4; + + cur_len = len_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]); + + len = MIN2(cur_len, len); + } + + return len; +} + +static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2]) +{ + float tdx, tdy; + + tdx = dx; + tdy = dy; + + if (outline) { + tdx += px[0]; + tdy += px[1]; + } + + glBegin(GL_QUADS); + glVertex3f(x - tdx, y + tdy, 0.0f); + glVertex3f(x + tdx, y + tdy, 0.0f); + glVertex3f(x + tdx, y - tdy, 0.0f); + glVertex3f(x - tdx, y - tdy, 0.0f); + glEnd(); +} + +static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2]) +{ + float tdx, tdy; + + tdx = dx * 2.0f; + tdy = dy * 2.0f; + + if (outline) { + tdx += px[0]; + tdy += px[1]; + } + + glBegin(GL_TRIANGLES); + glVertex3f(x, y, 0.0f); + glVertex3f(x - tdx, y, 0.0f); + glVertex3f(x, y + tdy, 0.0f); + glEnd(); +} + static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, float marker_pos[2], int outline, int sel, int act, int width, int height) { -#if 1 - /* XXX: not re-implemented yet */ - (void) sc; - (void) track; - (void) marker; - (void) marker_pos; - (void) outline; - (void) sel; - (void) act; - (void) width; - (void) height; -#else - float x, y, dx, dy, patdx, patdy, searchdx, searchdy, tdx, tdy; + float dx, dy, patdx, patdy, searchdx, searchdy; int tiny = sc->flag & SC_SHOW_TINY_MARKER; - float col[3], scol[3], px[2]; + float col[3], scol[3], px[2], side; if ((tiny && outline) || (marker->flag & MARKER_DISABLED)) return; @@ -757,8 +802,9 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo dx = 6.0f / width / sc->zoom; dy = 6.0f / height / sc->zoom; - patdx = MIN2(dx * 2.0f / 3.0f, (track->pat_max[0] - track->pat_min[0]) / 6.0f); - patdy = MIN2(dy * 2.0f / 3.0f, (track->pat_max[1] - track->pat_min[1]) / 6.0f); + side = get_shortest_pattern_side(marker); + patdx = MIN2(dx * 2.0f / 3.0f, side / 6.0f); + patdy = MIN2(dy * 2.0f / 3.0f, side * width / height / 6.0f); searchdx = MIN2(dx, (track->search_max[0] - track->search_min[0]) / 6.0f); searchdy = MIN2(dy, (track->search_max[1] - track->search_min[1]) / 6.0f); @@ -775,41 +821,10 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo } /* search offset square */ - x = track->search_min[0]; - y = track->search_max[1]; - - tdx = searchdx; - tdy = searchdy; - - if (outline) { - tdx += px[0]; - tdy += px[1]; - } - - glBegin(GL_QUADS); - glVertex3f(x - tdx, y + tdy, 0); - glVertex3f(x + tdx, y + tdy, 0); - glVertex3f(x + tdx, y - tdy, 0); - glVertex3f(x - tdx, y - tdy, 0); - glEnd(); + draw_marker_slide_square(track->search_min[0], track->search_max[1], searchdx, searchdy, outline, px); /* search re-sizing triangle */ - x = track->search_max[0]; - y = track->search_min[1]; - - tdx = searchdx * 2.0f; - tdy = searchdy * 2.0f; - - if (outline) { - tdx += px[0]; - tdy += px[1]; - } - - glBegin(GL_TRIANGLES); - glVertex3f(x, y, 0); - glVertex3f(x - tdx, y, 0); - glVertex3f(x, y + tdy, 0); - glEnd(); + draw_marker_slide_triangle(track->search_max[0], track->search_min[1], searchdx, searchdy, outline, px); } if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) { @@ -820,49 +835,32 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo glColor3fv(col); } - /* pattern offset square */ - x = track->pat_min[0]; - y = track->pat_max[1]; + /* XXX: need to be real check if affine tracking is enabled, but for now not + * sure how to do this, so assume affine tracker is always enabled */ + if (TRUE) { + int i; - tdx = patdx; - tdy = patdy; - - if (outline) { - tdx += px[0]; - tdy += px[1]; + /* pattern's corners sliding squares */ + for (i = 0; i < 4; i++) { + draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1], + patdx / 1.5f, patdy / 1.5f, outline, px); + } } + else { + /* pattern offset square */ + draw_marker_slide_square(marker->pattern_corners[3][0], marker->pattern_corners[3][1], + patdx, patdy, outline, px); - glBegin(GL_QUADS); - glVertex3f(x - tdx, y + tdy, 0); - glVertex3f(x + tdx, y + tdy, 0); - glVertex3f(x + tdx, y - tdy, 0); - glVertex3f(x - tdx, y - tdy, 0); - glEnd(); - - /* pattern re-sizing triangle */ - x = track->pat_max[0]; - y = track->pat_min[1]; - - tdx = patdx*2.0f; - tdy = patdy*2.0f; - - if (outline) { - tdx += px[0]; - tdy += px[1]; + /* pattern re-sizing triangle */ + draw_marker_slide_triangle(marker->pattern_corners[1][0], marker->pattern_corners[1][1], + patdx, patdy, outline, px); } - - glBegin(GL_TRIANGLES); - glVertex3f(x, y, 0); - glVertex3f(x - tdx, y, 0); - glVertex3f(x, y + tdy, 0); - glEnd(); } glPopMatrix(); if (outline) glLineWidth(1.0f); -#endif } static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 2db563643a3..c1bbc75c87a 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -444,8 +444,7 @@ static void clip_operatortypes(void) /* markers */ WM_operatortype_append(CLIP_OT_add_marker); - /* XXX: need porting! */ - //WM_operatortype_append(CLIP_OT_slide_marker); + WM_operatortype_append(CLIP_OT_slide_marker); WM_operatortype_append(CLIP_OT_delete_track); WM_operatortype_append(CLIP_OT_delete_marker); @@ -624,8 +623,7 @@ static void clip_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CLIP_OT_delete_marker", DELKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "CLIP_OT_delete_marker", XKEY, KM_PRESS, KM_SHIFT, 0); - /* XXX: need porting */ - //WM_keymap_add_item(keymap, "CLIP_OT_slide_marker", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "CLIP_OT_slide_marker", LEFTMOUSE, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "CLIP_OT_disable_markers", DKEY, KM_PRESS, KM_SHIFT, 0); RNA_enum_set(kmi->ptr, "action", 2); /* toggle */ diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 6021e0e15ce..d50bed005ab 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -248,8 +248,6 @@ void CLIP_OT_delete_marker(wmOperatorType *ot) } /********************** slide marker operator *********************/ -/* XXX: need porting! */ -#if 0 #define SLIDE_ACTION_POS 0 #define SLIDE_ACTION_SIZE 1 @@ -262,15 +260,16 @@ typedef struct { int mval[2]; int width, height; - float *min, *max, *pos, *offset; - float smin[2], smax[2], spos[2], soff[2]; + float *min, *max, *pos, *offset, (*corners)[2]; + float smin[2], smax[2], spos[2], soff[2], scorners[4][2]; float (*smarkers)[2]; int lock, accurate; } SlideMarkerData; static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTrack *track, - MovieTrackingMarker *marker, wmEvent *event, int area, int action, int width, int height) + MovieTrackingMarker *marker, wmEvent *event, + int area, int corner, int action, int width, int height) { SlideMarkerData *data = MEM_callocN(sizeof(SlideMarkerData), "slide marker data"); @@ -289,10 +288,9 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra } else if (area == TRACK_AREA_PAT) { if (action == SLIDE_ACTION_SIZE) { - data->min = track->pat_min; - data->max = track->pat_max; + data->corners = marker->pattern_corners; } - else { + else if (action == SLIDE_ACTION_OFFSET) { int a; data->pos = marker->pos; @@ -304,15 +302,28 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra for (a = 0; a < track->markersnr; a++) copy_v2_v2(data->smarkers[a], track->markers[a].pos); } + else if (action == SLIDE_ACTION_POS) { + data->corners = marker->pattern_corners; + data->pos = marker->pattern_corners[corner]; + + copy_v2_v2(data->spos, data->pos); + } } else if (area == TRACK_AREA_SEARCH) { data->min = track->search_min; data->max = track->search_max; } - if (area == TRACK_AREA_SEARCH || (area == TRACK_AREA_PAT && action != SLIDE_ACTION_OFFSET)) { - copy_v2_v2(data->smin, data->min); - copy_v2_v2(data->smax, data->max); + if ((area == TRACK_AREA_SEARCH) || + (area == TRACK_AREA_PAT && !ELEM(action, SLIDE_ACTION_OFFSET, SLIDE_ACTION_POS))) + { + if (data->corners) { + memcpy(data->scorners, data->corners, sizeof(data->scorners)); + } + else { + copy_v2_v2(data->smin, data->min); + copy_v2_v2(data->smax, data->max); + } } data->mval[0] = event->mval[0]; @@ -327,8 +338,6 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra return data; } -/* corner = 0: right-bottom corner, - * corner = 1: left-top corner */ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, int area, float co[2], int corner, int width, int height) { @@ -342,8 +351,7 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki copy_v2_v2(max, track->search_max); } else { - copy_v2_v2(min, track->pat_min); - copy_v2_v2(max, track->pat_max); + BKE_tracking_marker_pattern_minmax(marker, min, max); } dx = size / width / sc->zoom; @@ -371,22 +379,95 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki return inside; } +static int get_mouse_pattern_corner(SpaceClip *sc, MovieTrackingMarker *marker, float co[2], int width, int height) +{ + int i, next; + float len = FLT_MAX, dx, dy; + + for (i = 0; i < 4; i++) { + float cur_len; + + next = (i + 1) % 4; + + cur_len = len_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]); + + len = MIN2(cur_len, len); + } + + dx = 6.0f / width / sc->zoom; + dy = 6.0f / height / sc->zoom; + + dx = MIN2(dx * 2.0f / 3.0f, len / 6.0f); + dy = MIN2(dy * 2.0f / 3.0f, len * width / height / 6.0f); + + for (i = 0; i < 4; i++) { + float crn[2]; + int inside; + + add_v2_v2v2(crn, marker->pattern_corners[i], marker->pos); + + inside = IN_RANGE_INCL(co[0], crn[0] - dx, crn[0] + dx) && + IN_RANGE_INCL(co[1], crn[1] - dy, crn[1] + dy); + + if (inside) + return i; + } + + return -1; +} + static int mouse_on_offset(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, - float co[2], int width, int height) + float co[2], int width, int height) { float pos[2], dx, dy; + float pat_min[2], pat_max[2]; + + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); add_v2_v2v2(pos, marker->pos, track->offset); dx = 12.0f / width / sc->zoom; dy = 12.0f / height / sc->zoom; - dx = MIN2(dx, (track->pat_max[0] - track->pat_min[0]) / 2.0f); - dy = MIN2(dy, (track->pat_max[1] - track->pat_min[1]) / 2.0f); + dx = MIN2(dx, (pat_max[0] - pat_min[0]) / 2.0f); + dy = MIN2(dy, (pat_max[1] - pat_min[1]) / 2.0f); return co[0] >= pos[0] - dx && co[0] <= pos[0] + dx && co[1] >= pos[1] - dy && co[1] <= pos[1] + dy; } +static int slide_check_corners(float (*corners)[2]) +{ + int i, next, prev; + float cross = 0.0f; + float p[2] = {0.0f, 0.0f}; + + if (!isect_point_quad_v2(p, corners[0], corners[1], corners[2], corners[3])) + return FALSE; + + for (i = 0; i < 4; i++) { + float v1[2], v2[2], cur_cross; + + next = (i + 1) % 4; + prev = (4 + i - 1) % 4; + + sub_v2_v2v2(v1, corners[i], corners[prev]); + sub_v2_v2v2(v2, corners[next], corners[i]); + + cur_cross = cross_v2v2(v1, v2); + + if (fabsf(cur_cross) > FLT_EPSILON) { + if (cross == 0.0f) { + cross = cur_cross; + } + else if (cross * cur_cross < 0.0f) { + return FALSE; + } + } + } + + return TRUE; +} + static void hide_cursor(bContext *C) { wmWindow *win = CTX_wm_window(C); @@ -424,28 +505,45 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event) MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr); if ((marker->flag & MARKER_DISABLED) == 0) { - if (!customdata) + if (!customdata) { if (mouse_on_offset(sc, track, marker, co, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_POINT, + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_POINT, 0, SLIDE_ACTION_POS, width, height); + } if (sc->flag & SC_SHOW_MARKER_SEARCH) { - if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 1, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, + if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 1, width, height)) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, 0, SLIDE_ACTION_OFFSET, width, height); - else if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 0, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, + } + else if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 0, width, height)) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, 0, SLIDE_ACTION_SIZE, width, height); + } } if (!customdata && (sc->flag & SC_SHOW_MARKER_PATTERN)) { - if (mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 1, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, - SLIDE_ACTION_OFFSET, width, height); + /* XXX: need to be real check if affine tracking is enabled, but for now not + * sure how to do this, so assume affine tracker is always enabled */ + if (TRUE) { + int corner = get_mouse_pattern_corner(sc, marker, co, width, height); - if (!customdata && mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 0, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, - SLIDE_ACTION_SIZE, width, height); + if (corner != -1) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, corner, + SLIDE_ACTION_POS, width, height); + } + } + else { + if (mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 1, width, height)) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, 0, + SLIDE_ACTION_OFFSET, width, height); + } + + if (!customdata && mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 0, width, height)) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, 0, + SLIDE_ACTION_SIZE, width, height); + } + } } if (customdata) @@ -494,8 +592,13 @@ static void cancel_mouse_slide(SlideMarkerData *data) } else { if (data->action == SLIDE_ACTION_SIZE) { - copy_v2_v2(data->min, data->smin); - copy_v2_v2(data->max, data->smax); + if (data->corners) { + memcpy(data->corners, data->scorners, sizeof(data->scorners)); + } + else { + copy_v2_v2(data->min, data->smin); + copy_v2_v2(data->max, data->smax); + } } else { int a; @@ -569,18 +672,33 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) } else { if (data->action == SLIDE_ACTION_SIZE) { - data->min[0] = data->smin[0] - dx; - data->max[0] = data->smax[0] + dx; + if (data->corners) { + data->corners[0][0] = data->scorners[0][0] - dx; + data->corners[0][1] = data->scorners[0][1] + dy; - data->min[1] = data->smin[1] + dy; - data->max[1] = data->smax[1] - dy; + data->corners[1][0] = data->scorners[1][0] + dx; + data->corners[1][1] = data->scorners[1][1] + dy; + + data->corners[2][0] = data->scorners[2][0] + dx; + data->corners[2][1] = data->scorners[2][1] - dy; + + data->corners[3][0] = data->scorners[3][0] - dx; + data->corners[3][1] = data->scorners[3][1] - dy; + } + else { + data->min[0] = data->smin[0] - dx; + data->max[0] = data->smax[0] + dx; + + data->min[1] = data->smin[1] + dy; + data->max[1] = data->smax[1] - dy; + } if (data->area == TRACK_AREA_SEARCH) BKE_tracking_clamp_track(data->track, CLAMP_SEARCH_DIM); else BKE_tracking_clamp_track(data->track, CLAMP_PAT_DIM); } - else { + else if (data->action == SLIDE_ACTION_OFFSET) { float d[2] = {dx, dy}; if (data->area == TRACK_AREA_SEARCH) { @@ -599,6 +717,21 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) if (data->area == TRACK_AREA_SEARCH) BKE_tracking_clamp_track(data->track, CLAMP_SEARCH_POS); } + else if (data->action == SLIDE_ACTION_POS) { + float spos[2]; + + copy_v2_v2(spos, data->pos); + + data->pos[0] = data->spos[0] + dx; + data->pos[1] = data->spos[1] + dy; + + if (!slide_check_corners(data->corners)) { + copy_v2_v2(data->pos, spos); + } + + /* currently only patterns are allowed to have such combination of event and data */ + BKE_tracking_clamp_track(data->track, CLAMP_PAT_DIM); + } } WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL); @@ -651,8 +784,6 @@ void CLIP_OT_slide_marker(wmOperatorType *ot) "Offset", "Offset in floating point units, 1.0 is the width and height of the image", -FLT_MAX, FLT_MAX); } -#endif - /********************** mouse select operator *********************/ static int mouse_on_side(float co[2], float x1, float y1, float x2, float y2, float epsx, float epsy) @@ -854,8 +985,6 @@ static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) int extend = RNA_boolean_get(op->ptr, "extend"); if (!extend) { -#if 0 - /* XXX: need porting */ SlideMarkerData *slidedata = slide_marker_customdata(C, event); if (slidedata) { @@ -870,7 +999,6 @@ static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_PASS_THROUGH; } -#endif } ED_clip_mouse_pos(C, event, co); From b5ac36671a510a67eede9d89c8bf539f3509dc05 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 15 May 2012 14:01:02 +0000 Subject: [PATCH 044/183] Tomato: fixed crash when using manual calibration without GP strokes done --- source/blender/editors/space_clip/clip_draw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 7fd4f1bafae..aa9af704280 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1323,8 +1323,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, gpd = clip->gpd; } - - if (sc->flag & SC_MANUAL_CALIBRATION) { + if (sc->flag & SC_MANUAL_CALIBRATION && gpd) { bGPDlayer *layer = gpd->layers.first; while (layer) { From 3e4e7bfc42286af77e178e51d842256ccb9944a6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 15 May 2012 14:44:32 +0000 Subject: [PATCH 045/183] Tomato: fix usage of uninitialized variables in applyAspectRatio Thanks Keir for pointing into issue! --- source/blender/editors/transform/transform.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 26f313aadfb..2c19f44f7a3 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -305,10 +305,12 @@ void applyAspectRatio(TransInfo *t, float vec[2]) float aspx, aspy; int width, height; + ED_space_clip_size(sc, &width, &height); + if (t->options & CTX_MOVIECLIP) - ED_space_clip_size(sc, &width, &height); - else if (t->options & CTX_MASK) ED_space_clip_aspect(sc, &aspx, &aspy); + else if (t->options & CTX_MASK) + ED_space_clip_mask_aspect(sc, &aspx, &aspy); vec[0] *= width / aspx; vec[1] *= height / aspy; From e5927b8cc5bb9a5e06008ab29d04d70db70316e8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 15 May 2012 15:05:45 +0000 Subject: [PATCH 046/183] Tomato: fixes for marker sliding operator - Fixed crash on slide undo. Was caused by some typos in slide data initialization and not checking for slide action in cancel callback - Always create keyframe for frame when marker is stared sliding. --- source/blender/editors/space_clip/tracking_ops.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index d50bed005ab..89b14b06220 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -315,7 +315,7 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra } if ((area == TRACK_AREA_SEARCH) || - (area == TRACK_AREA_PAT && !ELEM(action, SLIDE_ACTION_OFFSET, SLIDE_ACTION_POS))) + (area == TRACK_AREA_PAT && action != SLIDE_ACTION_OFFSET)) { if (data->corners) { memcpy(data->scorners, data->corners, sizeof(data->scorners)); @@ -591,7 +591,9 @@ static void cancel_mouse_slide(SlideMarkerData *data) copy_v2_v2(data->pos, data->spos); } else { - if (data->action == SLIDE_ACTION_SIZE) { + if ((data->action == SLIDE_ACTION_SIZE) || + (data->action == SLIDE_ACTION_POS && data->area == TRACK_AREA_PAT)) + { if (data->corners) { memcpy(data->corners, data->scorners, sizeof(data->scorners)); } @@ -663,8 +665,6 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) else { data->pos[0] = data->spos[0] + dx; data->pos[1] = data->spos[1] + dy; - - data->marker->flag &= ~MARKER_TRACKED; } WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -734,6 +734,8 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) } } + data->marker->flag &= ~MARKER_TRACKED; + WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL); break; From 7e5348f4c5a464ebf3ec7f1bf532a0658f388283 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 May 2012 18:05:35 +0000 Subject: [PATCH 047/183] improvements to mask editor path editing - adding new points de-selects previous so Ctrl+Click+Drag works usefully. - cyclic curves now extrude properly - adding new points inbetween existing now use the surrounding points handle length. --- source/blender/blenkernel/BKE_mask.h | 4 +- source/blender/blenkernel/intern/mask.c | 100 +++++++++--------------- source/blender/editors/mask/mask_ops.c | 14 ++-- 3 files changed, 45 insertions(+), 73 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index be14229b323..26beed4645c 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -82,9 +82,9 @@ void BKE_mask_unlink(struct Main *bmain, struct Mask *mask); void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime); void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene); void BKE_mask_parent_init(struct MaskParent *parent); +void BKE_mask_calc_handle_adjacent_length(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); void BKE_mask_calc_handle_point(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); -void BKE_mask_calc_handle_point_auto(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, - const short do_length_match); +void BKE_mask_calc_handle_point_auto(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); void BKE_mask_get_handle_point_adjacent(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, struct MaskSplinePoint **r_point_prev, struct MaskSplinePoint **r_point_next); void BKE_mask_calc_handles(struct Mask *mask); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index d497ba612ae..0af0c1c7aa5 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -758,7 +758,7 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev { BezTriple *bezt = &point->bezt; BezTriple *prev_bezt = NULL, *next_bezt = NULL; - int handle_type = bezt->h1; + //int handle_type = bezt->h1; if (prev_point) prev_bezt = &prev_point->bezt; @@ -766,6 +766,9 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev if (next_point) next_bezt = &next_point->bezt; +#if 1 + BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); +#else if (handle_type == HD_VECT) { BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); } @@ -792,6 +795,7 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev add_v3_v3v3(bezt->vec[0], bezt->vec[1], h); sub_v3_v3v3(bezt->vec[2], bezt->vec[1], h); } +#endif } void BKE_mask_get_handle_point_adjacent(Mask *UNUSED(mask), MaskSpline *spline, MaskSplinePoint *point, @@ -851,85 +855,55 @@ static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dis } } +void BKE_mask_calc_handle_adjacent_length(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) +{ + /* TODO! - make this aspect aware! */ + int length_tot = 0; + float length_average = 0.0f; + + MaskSplinePoint *prev_point, *next_point; + BKE_mask_get_handle_point_adjacent(mask, spline, point, + &prev_point, &next_point); + + if (prev_point) { + length_average += len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]); + length_tot++; + } + + if (next_point) { + length_average += len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]); + length_tot++; + } + + if (length_tot) { + length_average /= (float)length_tot; + + enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); + enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + } +} + + /** * \brief Resets auto handles even for non-auto bezier points * * Useful for giving sane defaults. */ -void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, - const short do_length_match) +void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) { + /* TODO! - make this aspect aware! */ MaskSplinePoint *prev_point, *next_point; - const char h_back[2] = {point->bezt.h1, point->bezt.h2}; -int i1=999, i2=999; + BKE_mask_get_handle_point_adjacent(mask, spline, point, &prev_point, &next_point); - if (prev_point) i1 = (int)(prev_point - spline->points); - if (next_point) i2 = (int)(next_point - spline->points); - -printf("found points %d %d : %d\n", i1, i2, (int)(point - spline->points)); - point->bezt.h1 = HD_AUTO; point->bezt.h2 = HD_AUTO; mask_calc_point_handle(point, prev_point, next_point); point->bezt.h1 = h_back[0]; point->bezt.h2 = h_back[1]; - mask_calc_point_handle(point, prev_point, next_point); - - /* TODO! - make this aspect aware! */ - /* TODO! - not working right with cyclic curves, need to investigate! */ - if (do_length_match) { - int length_tot = 0; - float length_average = 0.0f; - - if (prev_point) { - length_average += len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]); - length_tot++; - } - - if (next_point) { - length_average += len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]); - length_tot++; - } - - if (length_tot) { - length_average /= (float)length_tot; - - enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); - enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); - } - } - - mask_calc_point_handle(point, prev_point, next_point); - - // XXX - if ((point->bezt.h1 == HD_ALIGN || point->bezt.h2 == HD_ALIGN) ){ - float vec[2]; - sub_v2_v2(point->bezt.vec[0], point->bezt.vec[1]); - sub_v2_v2(point->bezt.vec[2], point->bezt.vec[1]); - - copy_v2_v2(vec, point->bezt.vec[0]); - point->bezt.vec[0][0] = vec[1]; - point->bezt.vec[0][0] = -vec[0]; - add_v2_v2(point->bezt.vec[0], point->bezt.vec[1]); - - copy_v2_v2(vec, point->bezt.vec[2]); - point->bezt.vec[2][0] = vec[1]; - point->bezt.vec[2][0] = -vec[0]; - add_v2_v2(point->bezt.vec[2], point->bezt.vec[1]); - - copy_v2_v2(vec, point->bezt.vec[2]); - copy_v2_v2(point->bezt.vec[0], vec); - copy_v2_v2(point->bezt.vec[2], point->bezt.vec[0]); - - - - } - - mask_calc_point_handle(point, prev_point, next_point); } void BKE_mask_calc_handles(Mask *mask) diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 661030cb382..5518fedf91a 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1146,6 +1146,10 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask sub_v2_v2(bezt->vec[0], vec); add_v2_v2(bezt->vec[2], vec); + + if (reference_adjacent) { + BKE_mask_calc_handle_adjacent_length(mask, spline, new_point); + } } else { @@ -1196,10 +1200,10 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask add_v2_v2(bezt->vec[0], vec); sub_v2_v2(bezt->vec[2], vec); #else - BKE_mask_calc_handle_point_auto(mask, spline, new_point, TRUE); + BKE_mask_calc_handle_point_auto(mask, spline, new_point); + BKE_mask_calc_handle_adjacent_length(mask, spline, new_point); #endif - } BKE_mask_parent_init(&new_point->parent); @@ -1223,10 +1227,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) MaskSplinePoint *new_point_array, *new_point; int point_index = point - spline->points; - /* adding _could_ deselect, for now don't */ -#if 0 toggle_selection_all(mask, SEL_DESELECT); -#endif new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); @@ -1302,10 +1303,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) MaskSplinePoint *point; MaskSplinePoint *new_point = NULL, *ref_point = NULL; - /* adding _could_ deselect, for now don't */ -#if 0 toggle_selection_all(mask, SEL_DESELECT); -#endif shape = BKE_mask_shape_active(mask); From 0a917fa1c36f0544867297442f00216bf1021577 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Thu, 17 May 2012 02:31:52 +0000 Subject: [PATCH 048/183] Add new planar tracker features and use the new planar API This commit removes the use of the legacy RegionTracker API from Blender, and replaces it with the new TrackRegion API. This also adds several features to the planar tracker in libmv: - Do a brute-force initialization of tracking similar to "Hybrid" mode in the stable release, but using all floats. This is slower but more accurate. It is still necessary to evaluate if the performance loss is worth it. In particular, this change is necessary to support high bit depth imagery. - Add support for masks over the search window. This is a step towards supporting user-defined tracker masks. The tracker masks will make it easy for users to make a mask for e.g. a ball. - Add Pearson product moment correlation coefficient checking (aka "Correlation" in the UI. This causes tracking failure if the tracked patch is not linearly related to the template. - Add support for warping a few points in addition to the supplied points. This is useful because the tracking code deliberately does not expose the underlying warp representation. Instead, warps are specified in an aparametric way via the correspondences. - Remove the "num_samples_xy" concept and replace it with automatic determination of the number of samples. This makes the API easier for users. - Fix various bugs in the parameterizations. There remains a bug with subpixel precision tracking when in "keyframe" mode; this will get fixed shortly. --- extern/libmv/libmv-capi.cpp | 132 +++--- extern/libmv/libmv-capi.h | 2 - .../libmv/tracking/esm_region_tracker.cc | 2 - extern/libmv/libmv/tracking/track_region.cc | 440 ++++++++++++++++-- extern/libmv/libmv/tracking/track_region.h | 28 +- source/blender/blenkernel/intern/tracking.c | 346 +++++++++----- source/blender/makesdna/DNA_tracking_types.h | 22 +- 7 files changed, 749 insertions(+), 223 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index ddf69ce5e28..7d3dca5c4e8 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -28,6 +28,10 @@ tracking between which failed */ #undef DUMP_FAILURE +/* define this to generate PNG images with content of search areas + on every itteration of tracking */ +#undef DUMP_ALWAYS + #include "libmv-capi.h" #include "third_party/gflags/gflags/gflags.h" @@ -60,7 +64,7 @@ #include #include -#ifdef DUMP_FAILURE +#if defined(DUMP_FAILURE) || defined (DUMP_ALWAYS) # include #endif @@ -172,7 +176,7 @@ static void floatBufToImage(const float *buf, int width, int height, libmv::Floa } } -#ifdef DUMP_FAILURE +#if defined(DUMP_FAILURE) || defined (DUMP_ALWAYS) void savePNGImage(png_bytep *row_pointers, int width, int height, int depth, int color_type, char *file_name) { png_infop info_ptr; @@ -306,16 +310,20 @@ int libmv_regionTrackerTrack(libmv_RegionTracker *libmv_tracker, const float *im floatBufToImage(ima1, width, height, &old_patch); floatBufToImage(ima2, width, height, &new_patch); -#ifndef DUMP_FAILURE +#if !defined(DUMP_FAILURE) && !defined(DUMP_ALWAYS) return region_tracker->Track(old_patch, new_patch, x1, y1, x2, y2); #else { - double sx2 = *x2, sy2 = *y2; + /* double sx2 = *x2, sy2 = *y2; */ int result = region_tracker->Track(old_patch, new_patch, x1, y1, x2, y2); +#if defined(DUMP_ALWAYS) + { +#else if (!result) { +#endif saveImage("old_patch", old_patch, x1, y1); - saveImage("new_patch", new_patch, sx2, sy2); + saveImage("new_patch", new_patch, *x2, *y2); } return result; @@ -334,65 +342,81 @@ void libmv_regionTrackerDestroy(libmv_RegionTracker *libmv_tracker) /* TrackRegion (new planar tracker) */ int libmv_trackRegion(const struct libmv_trackRegionOptions *options, - const float *image1, const float *image2, - int width, int height, - const double *x1, const double *y1, - struct libmv_trackRegionResult *result, - double *x2, double *y2) { - double xx1[4], yy1[4]; - double xx2[4], yy2[4]; + const float *image1, const float *image2, + int width, int height, + const double *x1, const double *y1, + struct libmv_trackRegionResult *result, + double *x2, double *y2) +{ + double xx1[5], yy1[5]; + double xx2[5], yy2[5]; + bool tracking_result = false; - // Convert to doubles for the libmv api. - for (int i = 0; i < 4; ++i) { - xx1[i] = x1[i]; - yy1[i] = y1[i]; - xx2[i] = x2[i]; - yy2[i] = y2[i]; - } + /* Convert to doubles for the libmv api. The four corners and the center. */ + for (int i = 0; i < 5; ++i) { + xx1[i] = x1[i]; + yy1[i] = y1[i]; + xx2[i] = x2[i]; + yy2[i] = y2[i]; + } - libmv::TrackRegionOptions track_region_options; - switch (options->motion_model) { + libmv::TrackRegionOptions track_region_options; + switch (options->motion_model) { #define LIBMV_CONVERT(the_model) \ case libmv::TrackRegionOptions::the_model: \ track_region_options.mode = libmv::TrackRegionOptions::the_model; \ break; - LIBMV_CONVERT(TRANSLATION) - LIBMV_CONVERT(TRANSLATION_ROTATION) - LIBMV_CONVERT(TRANSLATION_SCALE) - LIBMV_CONVERT(TRANSLATION_ROTATION_SCALE) - LIBMV_CONVERT(AFFINE) - LIBMV_CONVERT(HOMOGRAPHY) + LIBMV_CONVERT(TRANSLATION) + LIBMV_CONVERT(TRANSLATION_ROTATION) + LIBMV_CONVERT(TRANSLATION_SCALE) + LIBMV_CONVERT(TRANSLATION_ROTATION_SCALE) + LIBMV_CONVERT(AFFINE) + LIBMV_CONVERT(HOMOGRAPHY) #undef LIBMV_CONVERT - } - track_region_options.num_samples_x = options->num_samples_x; - track_region_options.num_samples_y = options->num_samples_y; - track_region_options.minimum_correlation = options->minimum_correlation; - track_region_options.max_iterations = options->num_iterations; - track_region_options.sigma = options->sigma; - - // Convert from raw float buffers to libmv's FloatImage. - libmv::FloatImage old_patch, new_patch; - floatBufToImage(image1, width, height, &old_patch); - floatBufToImage(image2, width, height, &new_patch); + } - libmv::TrackRegionResult track_region_result; - libmv::TrackRegion(old_patch, new_patch, xx1, yy1, track_region_options, xx2, yy2, &track_region_result); + track_region_options.minimum_correlation = options->minimum_correlation; + track_region_options.max_iterations = options->num_iterations; + track_region_options.sigma = options->sigma; + track_region_options.num_extra_points = 1; + track_region_options.image1_mask = NULL; - // Convert to floats for the blender api. - for (int i = 0; i < 4; ++i) { - x2[i] = xx2[i]; - y2[i] = yy2[i]; - } + /* Convert from raw float buffers to libmv's FloatImage. */ + libmv::FloatImage old_patch, new_patch; + floatBufToImage(image1, width, height, &old_patch); + floatBufToImage(image2, width, height, &new_patch); - // TODO(keir): Update the termination string with failure details. - if (track_region_result.termination == libmv::TrackRegionResult::PARAMETER_TOLERANCE || - track_region_result.termination == libmv::TrackRegionResult::FUNCTION_TOLERANCE || - track_region_result.termination == libmv::TrackRegionResult::GRADIENT_TOLERANCE || - track_region_result.termination == libmv::TrackRegionResult::NO_CONVERGENCE || - track_region_result.termination == libmv::TrackRegionResult::INSUFFICIENT_CORRELATION) { - return true; - } - return false; + libmv::TrackRegionResult track_region_result; + libmv::TrackRegion(old_patch, new_patch, xx1, yy1, track_region_options, xx2, yy2, &track_region_result); + + /* Convert to floats for the blender api. */ + for (int i = 0; i < 5; ++i) { + x2[i] = xx2[i]; + y2[i] = yy2[i]; + } + + /* TODO(keir): Update the termination string with failure details. */ + if (track_region_result.termination == libmv::TrackRegionResult::PARAMETER_TOLERANCE || + track_region_result.termination == libmv::TrackRegionResult::FUNCTION_TOLERANCE || + track_region_result.termination == libmv::TrackRegionResult::GRADIENT_TOLERANCE || + track_region_result.termination == libmv::TrackRegionResult::NO_CONVERGENCE || + track_region_result.termination == libmv::TrackRegionResult::INSUFFICIENT_CORRELATION) + { + tracking_result = true; + } + +#if defined(DUMP_FAILURE) || defined(DUMP_ALWAYS) +#if defined(DUMP_ALWAYS) + { +#else + if (!tracking_result) { +#endif + saveImage("old_patch", old_patch, x1[4], y1[4]); + saveImage("new_patch", new_patch, x2[4], y2[4]); + } +#endif + + return tracking_result; } /* ************ Tracks ************ */ diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index d7d132d4f21..d3f02f99e51 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -53,8 +53,6 @@ void libmv_regionTrackerDestroy(struct libmv_RegionTracker *libmv_tracker); /* TrackRegion (new planar tracker) */ struct libmv_trackRegionOptions { int motion_model; - int num_samples_x; - int num_samples_y; int num_iterations; double minimum_correlation; double sigma; diff --git a/extern/libmv/libmv/tracking/esm_region_tracker.cc b/extern/libmv/libmv/tracking/esm_region_tracker.cc index e6d0b9830f4..a8dc46d439b 100644 --- a/extern/libmv/libmv/tracking/esm_region_tracker.cc +++ b/extern/libmv/libmv/tracking/esm_region_tracker.cc @@ -98,8 +98,6 @@ bool EsmRegionTracker::Track(const FloatImage &image1, TrackRegionOptions options; options.mode = TrackRegionOptions::TRANSLATION; - options.num_samples_x = 2 * half_window_size + 1; - options.num_samples_y = 2 * half_window_size + 1; options.max_iterations = 20; options.sigma = sigma; options.use_esm = true; diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index 0bb8ae221b1..0dac56aeff7 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -38,6 +38,19 @@ namespace libmv { +TrackRegionOptions::TrackRegionOptions() + : mode(TRANSLATION), + minimum_correlation(0), + max_iterations(20), + use_esm(true), + use_brute_initialization(true), + sigma(0.9), + num_extra_points(0), + image1_mask(NULL) { +} + +namespace { + // TODO(keir): Consider adding padding. template bool InBounds(const FloatImage &image, @@ -161,22 +174,26 @@ class WarpCostFunctor { const FloatImage &image_and_gradient1, const FloatImage &image_and_gradient2, const Mat3 &canonical_to_image1, + int num_samples_x, + int num_samples_y, const Warp &warp) : options_(options), image_and_gradient1_(image_and_gradient1), image_and_gradient2_(image_and_gradient2), canonical_to_image1_(canonical_to_image1), + num_samples_x_(num_samples_x), + num_samples_y_(num_samples_y), warp_(warp) {} - template - bool operator()(const T *warp_parameters, T *residuals) const { - for (int i = 0; i < Warp::NUM_PARAMETERS; ++i) { - VLOG(2) << "warp_parameters[" << i << "]: " << warp_parameters[i]; - } + template + bool operator()(const T *warp_parameters, T *residuals) const { + for (int i = 0; i < Warp::NUM_PARAMETERS; ++i) { + VLOG(2) << "warp_parameters[" << i << "]: " << warp_parameters[i]; + } - int cursor = 0; - for (int r = 0; r < options_.num_samples_y; ++r) { - for (int c = 0; c < options_.num_samples_x; ++c) { + int cursor = 0; + for (int r = 0; r < num_samples_y_; ++r) { + for (int c = 0; c < num_samples_x_; ++c) { // Compute the location of the source pixel (via homography). Vec3 image1_position = canonical_to_image1_ * Vec3(c, r, 1); image1_position /= image1_position(2); @@ -223,17 +240,102 @@ class WarpCostFunctor { } // The difference is the error. + T error = src_sample - dst_sample; + + // Weight the error by the mask, if one is present. + if (options_.image1_mask != NULL) { + error *= T(AutoDiff::Sample(*options_.image1_mask, + image1_position[0], + image1_position[1])); + } residuals[cursor++] = src_sample - dst_sample; } } return true; } + // TODO(keir): Consider also computing the cost here. + double PearsonProductMomentCorrelationCoefficient( + const double *warp_parameters) const { + for (int i = 0; i < Warp::NUM_PARAMETERS; ++i) { + VLOG(2) << "Correlation warp_parameters[" << i << "]: " + << warp_parameters[i]; + } + + // The single-pass PMCC computation is somewhat numerically unstable, but + // it's sufficient for the tracker. + double sX = 0, sY = 0, sXX = 0, sYY = 0, sXY = 0; + + // Due to masking, it's important to account for fractional samples. + // Samples with a 50% mask get counted as a half sample. + double num_samples = 0; + + for (int r = 0; r < num_samples_y_; ++r) { + for (int c = 0; c < num_samples_x_; ++c) { + // Compute the location of the source pixel (via homography). + // TODO(keir): Cache these projections. + Vec3 image1_position = canonical_to_image1_ * Vec3(c, r, 1); + image1_position /= image1_position(2); + + // Compute the location of the destination pixel. + double image2_position[2]; + warp_.Forward(warp_parameters, + image1_position[0], + image1_position[1], + &image2_position[0], + &image2_position[1]); + + double x = AutoDiff::Sample(image_and_gradient2_, + image2_position[0], + image2_position[1]); + + double y = AutoDiff::Sample(image_and_gradient1_, + image1_position[0], + image1_position[1]); + + // Weight the signals by the mask, if one is present. + if (options_.image1_mask != NULL) { + double mask_value = AutoDiff::Sample(*options_.image1_mask, + image1_position[0], + image1_position[1]); + x *= mask_value; + y *= mask_value; + num_samples += mask_value; + } else { + num_samples++; + } + sX += x; + sY += y; + sXX += x*x; + sYY += y*y; + sXY += x*y; + } + } + // Normalize. + sX /= num_samples; + sY /= num_samples; + sXX /= num_samples; + sYY /= num_samples; + sXY /= num_samples; + + double var_x = sXX - sX*sX; + double var_y = sYY - sY*sY; + double covariance_xy = sXY - sX*sY; + + double correlation = covariance_xy / sqrt(var_x * var_y); + LG << "Covariance xy: " << covariance_xy + << ", var 1: " << var_x << ", var 2: " << var_y + << ", correlation: " << correlation; + return correlation; + } + private: const TrackRegionOptions &options_; const FloatImage &image_and_gradient1_; const FloatImage &image_and_gradient2_; const Mat3 &canonical_to_image1_; + int num_samples_x_; + int num_samples_y_; const Warp &warp_; }; @@ -260,9 +362,7 @@ Mat3 ComputeCanonicalHomography(const double *x1, class Quad { public: - Quad(const double *x, const double *y) - : x_(x), y_(y) { - + Quad(const double *x, const double *y) : x_(x), y_(y) { // Compute the centroid and store it. centroid_ = Vec2(0.0, 0.0); for (int i = 0; i < 4; ++i) { @@ -298,7 +398,7 @@ class Quad { struct TranslationWarp { TranslationWarp(const double *x1, const double *y1, const double *x2, const double *y2) { - Vec2 t = Quad(x1, y1).Centroid() - Quad(x2, y2).Centroid(); + Vec2 t = Quad(x2, y2).Centroid() - Quad(x1, y1).Centroid() ; parameters[0] = t[0]; parameters[1] = t[1]; } @@ -310,6 +410,13 @@ struct TranslationWarp { *y2 = y1 + warp_parameters[1]; } + template + void Backward(const T *warp_parameters, + const T &x2, const T& y2, T *x1, T* y1) const { + *x1 = x2 - warp_parameters[0]; + *y1 = y2 - warp_parameters[1]; + } + // Translation x, translation y. enum { NUM_PARAMETERS = 2 }; double parameters[NUM_PARAMETERS]; @@ -322,7 +429,7 @@ struct TranslationScaleWarp { Quad q2(x2, y2); // The difference in centroids is the best guess for translation. - Vec2 t = q1.Centroid() - q2.Centroid(); + Vec2 t = q2.Centroid() - q1.Centroid(); parameters[0] = t[0]; parameters[1] = t[1]; @@ -354,6 +461,12 @@ struct TranslationScaleWarp { *y2 = y1_scaled + warp_parameters[1]; } + template + void Backward(const T *warp_parameters, + const T &x2, const T& y2, T *x1, T* y1) const { + // XXX + } + // Translation x, translation y, scale. enum { NUM_PARAMETERS = 3 }; double parameters[NUM_PARAMETERS]; @@ -375,7 +488,7 @@ struct TranslationRotationWarp { Quad q2(x2, y2); // The difference in centroids is the best guess for translation. - Vec2 t = q1.Centroid() - q2.Centroid(); + Vec2 t = q2.Centroid() - q1.Centroid(); parameters[0] = t[0]; parameters[1] = t[1]; @@ -387,6 +500,10 @@ struct TranslationRotationWarp { } Mat2 R = OrthogonalProcrustes(correlation_matrix); parameters[2] = acos(R(0, 0)); + + std::cout << "correlation_matrix:\n" << correlation_matrix << "\n"; + std::cout << "R:\n" << R << "\n"; + std::cout << "theta:" << parameters[2] << "\n"; } // The strange way of parameterizing the translation and rotation is to make @@ -422,6 +539,12 @@ struct TranslationRotationWarp { *y2 = y1_rotated + warp_parameters[1]; } + template + void Backward(const T *warp_parameters, + const T &x2, const T& y2, T *x1, T* y1) const { + // XXX + } + // Translation x, translation y, rotation about the center of Q1 degrees. enum { NUM_PARAMETERS = 3 }; double parameters[NUM_PARAMETERS]; @@ -436,7 +559,7 @@ struct TranslationRotationScaleWarp { Quad q2(x2, y2); // The difference in centroids is the best guess for translation. - Vec2 t = q1.Centroid() - q2.Centroid(); + Vec2 t = q2.Centroid() - q1.Centroid(); parameters[0] = t[0]; parameters[1] = t[1]; @@ -449,8 +572,11 @@ struct TranslationRotationScaleWarp { correlation_matrix += q1.CornerRelativeToCentroid(i) * q2.CornerRelativeToCentroid(i).transpose(); } + std::cout << "correlation_matrix:\n" << correlation_matrix << "\n"; Mat2 R = OrthogonalProcrustes(correlation_matrix); + std::cout << "R:\n" << R << "\n"; parameters[3] = acos(R(0, 0)); + std::cout << "theta:" << parameters[3] << "\n"; } // The strange way of parameterizing the translation and rotation is to make @@ -471,7 +597,7 @@ struct TranslationRotationScaleWarp { const T y1_origin = y1 - q1.Centroid()(1); // Rotate about the origin (i.e. centroid of Q1). - const T theta = warp_parameters[2]; + const T theta = warp_parameters[3]; const T costheta = cos(theta); const T sintheta = sin(theta); const T x1_origin_rotated = costheta * x1_origin - sintheta * y1_origin; @@ -491,6 +617,12 @@ struct TranslationRotationScaleWarp { *y2 = y1_rotated_scaled + warp_parameters[1]; } + template + void Backward(const T *warp_parameters, + const T &x2, const T& y2, T *x1, T* y1) const { + // XXX + } + // Translation x, translation y, rotation about the center of Q1 degrees, // scale. enum { NUM_PARAMETERS = 4 }; @@ -542,10 +674,216 @@ struct HomographyWarp { *y2 = yy2 / zz2; } + template + void Backward(const T *warp_parameters, + const T &x2, const T& y2, T *x1, T* y1) const { + // XXX + } + enum { NUM_PARAMETERS = 8 }; double parameters[NUM_PARAMETERS]; }; +// Determine the number of samples to use for x and y. Quad winding goes: +// +// 0 1 +// 3 2 +// +// The idea is to take the maximum x or y distance. This may be oversampling. +// TODO(keir): Investigate the various choices; perhaps average is better? +void PickSampling(const double *x1, const double *y1, + const double *x2, const double *y2, + int *num_samples_x, int *num_samples_y) { + Vec2 a0(x1[0], y1[0]); + Vec2 a1(x1[1], y1[1]); + Vec2 a2(x1[2], y1[2]); + Vec2 a3(x1[3], y1[3]); + + Vec2 b0(x1[0], y1[0]); + Vec2 b1(x1[1], y1[1]); + Vec2 b2(x1[2], y1[2]); + Vec2 b3(x1[3], y1[3]); + + double x_dimensions[4] = { + (a1 - a0).norm(), + (a3 - a2).norm(), + (b1 - b0).norm(), + (b3 - b2).norm() + }; + + double y_dimensions[4] = { + (a3 - a0).norm(), + (a1 - a2).norm(), + (b3 - b0).norm(), + (b1 - b2).norm() + }; + const double kScaleFactor = 1.0; + *num_samples_x = static_cast( + kScaleFactor * *std::max_element(x_dimensions, x_dimensions + 4)); + *num_samples_y = static_cast( + kScaleFactor * *std::max_element(y_dimensions, y_dimensions + 4)); + LG << "Automatic num_samples_x: " << *num_samples_x + << ", num_samples_y: " << *num_samples_y; +} + +bool SearchAreaTooBigForDescent(const FloatImage &image2, + const double *x2, const double *y2) { + // TODO(keir): Check the bounds and enable only when it makes sense. + return true; +} + +bool PointOnRightHalfPlane(const Vec2 &a, const Vec2 &b, double x, double y) { + Vec2 ba = b - a; + return ((Vec2(x, y) - b).transpose() * Vec2(-ba.y(), ba.x())) > 0; +} + +// Determine if a point is in a quad. The quad is arranged as: +// +// +--> x +// | +// | 0 1 +// v 3 2 +// y +// +// The idea is to take the maximum x or y distance. This may be oversampling. +// TODO(keir): Investigate the various choices; perhaps average is better? +bool PointInQuad(const double *xs, const double *ys, double x, double y) { + Vec2 a0(xs[0], ys[0]); + Vec2 a1(xs[1], ys[1]); + Vec2 a2(xs[2], ys[2]); + Vec2 a3(xs[3], ys[3]); + + return PointOnRightHalfPlane(a0, a1, x, y) && + PointOnRightHalfPlane(a1, a2, x, y) && + PointOnRightHalfPlane(a2, a3, x, y) && + PointOnRightHalfPlane(a3, a0, x, y); +} + +typedef Eigen::Array FloatArray; + +// This creates a pattern in the frame of image2, from the pixel is image1, +// based on the initial guess represented by the two quads x1, y1, and x2, y2. +template +void CreateBrutePattern(const double *x1, const double *y1, + const double *x2, const double *y2, + const FloatImage &image1, + const FloatImage *image1_mask, + FloatArray *pattern, + FloatArray *mask, + int *origin_x, + int *origin_y) { + // Get integer bounding box of quad2 in image2. + int min_x = static_cast(floor(*std::min_element(x2, x2 + 4))); + int min_y = static_cast(floor(*std::min_element(y2, y2 + 4))); + int max_x = static_cast(ceil (*std::max_element(x2, x2 + 4))); + int max_y = static_cast(ceil (*std::max_element(y2, y2 + 4))); + + int w = max_x - min_x; + int h = max_y - min_y; + + pattern->resize(h, w); + mask->resize(h, w); + + Warp inverse_warp(x2, y2, x1, y1); + + // r,c are in the coordinate frame of image2. + for (int r = min_y; r < max_y; ++r) { + for (int c = min_x; c < max_x; ++c) { + // i and j are in the coordinate frame of the pattern in image2. + int i = r - min_y; + int j = c - min_x; + + double dst_x = c; + double dst_y = r; + double src_x; + double src_y; + inverse_warp.Forward(inverse_warp.parameters, + dst_x, dst_y, + &src_x, &src_y); + + if (PointInQuad(x1, y1, src_x, src_y)) { + (*pattern)(i, j) = SampleLinear(image1, src_y, src_x); + (*mask)(i, j) = 1.0; + if (image1_mask) { + (*mask)(i, j) = SampleLinear(*image1_mask, src_y, src_x);; + } + } else { + (*pattern)(i, j) = 0.0; + (*mask)(i, j) = 0.0; + } + } + } + *origin_x = min_x; + *origin_y = min_y; +} + +template +void BruteTranslationOnlyInitialize(const FloatImage &image1, + const FloatImage *image1_mask, + const FloatImage &image2, + const int num_extra_points, + const double *x1, const double *y1, + double *x2, double *y2) { + // Create the pattern to match in the space of image2, assuming our inital + // guess isn't too far from the template in image1. If there is no image1 + // mask, then the resulting mask is binary. + FloatArray pattern; + FloatArray mask; + int origin_x = -1, origin_y = -1; + CreateBrutePattern(x1, y1, x2, y2, image1, image1_mask, + &pattern, &mask, &origin_x, &origin_y); + + // Use Eigen on the images via maps for strong vectorization. + Map search(image2.Data(), image2.Height(), image2.Width()); + + // Try all possible locations inside the search area. Yes, everywhere. + // + // TODO(keir): There are a number of possible optimizations here. One choice + // is to make a grid and only try one out of every N possible samples. + // + // Another, slightly more clever idea, is to compute some sort of spatial + // frequency distribution of the pattern patch. If the spatial resolution is + // high (e.g. a grating pattern or fine lines) then checking every possible + // translation is necessary, since a 1-pixel shift may induce a massive + // change in the cost function. If the image is a blob or splotch with blurry + // edges, then fewer samples are necessary since a few pixels offset won't + // change the cost function much. + double best_sad = std::numeric_limits::max(); + int best_r = -1; + int best_c = -1; + int w = pattern.cols(); + int h = pattern.rows(); + for (int r = 0; r < (image2.Height() - h); ++r) { + for (int c = 0; c < (image2.Width() - w); ++c) { + // Compute the weighted sum of absolute differences, Eigen style. + double sad = (mask * (pattern - search.block(r, c, h, w))).abs().sum(); + if (sad < best_sad) { + best_r = r; + best_c = c; + best_sad = sad; + } + } + } + CHECK_NE(best_r, -1); + CHECK_NE(best_c, -1); + + LG << "Brute force translation found a shift. " + << "best_c: " << best_c << ", best_r: " << best_r << ", " + << "origin_x: " << origin_x << ", origin_y: " << origin_y << ", " + << "dc: " << (best_c - origin_x) << ", " + << "dr: " << (best_r - origin_y) + << ", tried " << ((image2.Height() - h) * (image2.Width() - w)) + << " shifts."; + + // Apply the shift. + for (int i = 0; i < 4 + num_extra_points; ++i) { + x2[i] += best_c - origin_x; + y2[i] += best_r - origin_y; + } +} + +} // namespace + template void TemplatedTrackRegion(const FloatImage &image1, const FloatImage &image2, @@ -553,6 +891,12 @@ void TemplatedTrackRegion(const FloatImage &image1, const TrackRegionOptions &options, double *x2, double *y2, TrackRegionResult *result) { + for (int i = 0; i < 4; ++i) { + LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); guess (" + << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", " + << (y2[i] - y1[i]) << ")."; + } + // Bail early if the points are already outside. if (!AllInBounds(image1, x1, y1)) { result->termination = TrackRegionResult::SOURCE_OUT_OF_BOUNDS; @@ -564,6 +908,19 @@ void TemplatedTrackRegion(const FloatImage &image1, } // TODO(keir): Check quads to ensure there is some area. + // Prepare the initial warp parameters from the four correspondences. + Warp warp(x1, y1, x2, y2); + + // Decide how many samples to use in the x and y dimensions. + int num_samples_x; + int num_samples_y; + PickSampling(x1, y1, x2, y2, &num_samples_x, &num_samples_y); + + // Compute the warp from rectangular coordinates. + Mat3 canonical_homography = ComputeCanonicalHomography(x1, y1, + num_samples_x, + num_samples_y); + // Prepare the image and gradient. Array3Df image_and_gradient1; Array3Df image_and_gradient2; @@ -572,8 +929,16 @@ void TemplatedTrackRegion(const FloatImage &image1, BlurredImageAndDerivativesChannels(image2, options.sigma, &image_and_gradient2); - // Prepare the initial warp parameters from the four correspondences. - Warp warp(x1, y1, x2, y2); + // Possibly do a brute-force translation-only initialization. + if (SearchAreaTooBigForDescent(image2, x2, y2) && + options.use_brute_initialization) { + LG << "Running brute initialization..."; + BruteTranslationOnlyInitialize(image_and_gradient1, + options.image1_mask, + image2, + options.num_extra_points, + x1, y1, x2, y2); + } ceres::Solver::Options solver_options; solver_options.linear_solver_type = ceres::DENSE_QR; @@ -591,17 +956,14 @@ void TemplatedTrackRegion(const FloatImage &image1, BoundaryCheckingCallback callback(image2, warp, x1, y1); solver_options.callbacks.push_back(&callback); - // Compute the warp from rectangular coordinates. - Mat3 canonical_homography = ComputeCanonicalHomography(x1, y1, - options.num_samples_x, - options.num_samples_y); - // Construct the warp cost function. AutoDiffCostFunction takes ownership. - WarpCostFunctor *cost_function = + WarpCostFunctor *warp_cost_function = new WarpCostFunctor(options, image_and_gradient1, image_and_gradient2, canonical_homography, + num_samples_x, + num_samples_y, warp); // Construct the problem with a single residual. @@ -612,8 +974,8 @@ void TemplatedTrackRegion(const FloatImage &image1, new ceres::AutoDiffCostFunction< WarpCostFunctor, ceres::DYNAMIC, - Warp::NUM_PARAMETERS>(cost_function, - options.num_samples_x * options.num_samples_y), + Warp::NUM_PARAMETERS>(warp_cost_function, + num_samples_x * num_samples_y), NULL, warp.parameters); @@ -624,11 +986,17 @@ void TemplatedTrackRegion(const FloatImage &image1, // Update the four points with the found solution; if the solver failed, then // the warp parameters are the identity (so ignore failure). - for (int i = 0; i < 4; ++i) { + // + // Also warp any extra points on the end of the array. + for (int i = 0; i < 4 + options.num_extra_points; ++i) { warp.Forward(warp.parameters, x1[i], y1[i], x2 + i, y2 + i); + LG << "Warped point " << i << ": (" << x1[i] << ", " << y1[i] << ") -> (" + << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", " + << (y2[i] - y1[i]) << ")."; } // TODO(keir): Update the result statistics. + // TODO(keir): Add a normalize-cross-correlation variant. CHECK_NE(summary.termination_type, ceres::USER_ABORT) << "Libmv bug."; if (summary.termination_type == ceres::USER_ABORT) { @@ -640,12 +1008,26 @@ void TemplatedTrackRegion(const FloatImage &image1, result->termination = TrackRegionResult::termination_enum; \ return; \ } + + // Avoid computing correlation for tracking failures. + HANDLE_TERMINATION(DID_NOT_RUN); + HANDLE_TERMINATION(NUMERICAL_FAILURE); + + // Otherwise, run a final correlation check. + if (options.minimum_correlation > 0.0) { + result->correlation = warp_cost_function-> + PearsonProductMomentCorrelationCoefficient(warp.parameters); + if (result->correlation < options.minimum_correlation) { + LG << "Failing with insufficient correlation."; + result->termination = TrackRegionResult::INSUFFICIENT_CORRELATION; + return; + } + } + HANDLE_TERMINATION(PARAMETER_TOLERANCE); HANDLE_TERMINATION(FUNCTION_TOLERANCE); HANDLE_TERMINATION(GRADIENT_TOLERANCE); HANDLE_TERMINATION(NO_CONVERGENCE); - HANDLE_TERMINATION(DID_NOT_RUN); - HANDLE_TERMINATION(NUMERICAL_FAILURE); #undef HANDLE_TERMINATION }; diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h index 7c937c04794..1a1346f544f 100644 --- a/extern/libmv/libmv/tracking/track_region.h +++ b/extern/libmv/libmv/tracking/track_region.h @@ -32,6 +32,8 @@ namespace libmv { struct TrackRegionOptions { + TrackRegionOptions(); + enum Mode { TRANSLATION, TRANSLATION_ROTATION, @@ -42,9 +44,6 @@ struct TrackRegionOptions { }; Mode mode; - int num_samples_x; - int num_samples_y; - double minimum_correlation; int max_iterations; @@ -52,13 +51,28 @@ struct TrackRegionOptions { // convergence speed at the cost of more per-iteration work. bool use_esm; + // If true, apply a brute-force translation-only search before attempting the + // full search. This is not enabled if the destination image ("image2") is + // too small; in that case eithen the basin of attraction is close enough + // that the nearby minima is correct, or the search area is too small. + bool use_brute_initialization; + double sigma; + + // Extra points that should get transformed by the warp. This is useful + // because the actual warp parameters are not exposed. + int num_extra_points; + + // If non-null, this is used as the pattern mask. It should match the size of + // image1, even though only values inside the image1 quad are examined. The + // values must be in the range 0.0 to 0.1. + FloatImage *image1_mask; }; struct TrackRegionResult { enum Termination { - // Ceres termination types, duplicated. - PARAMETER_TOLERANCE = 0, + // Ceres termination types, duplicated; though, not the int values. + PARAMETER_TOLERANCE, FUNCTION_TOLERANCE, GRADIENT_TOLERANCE, NO_CONVERGENCE, @@ -70,6 +84,7 @@ struct TrackRegionResult { DESTINATION_OUT_OF_BOUNDS, FELL_OUT_OF_BOUNDS, INSUFFICIENT_CORRELATION, + CONFIGURATION_ERROR, }; Termination termination; @@ -77,6 +92,7 @@ struct TrackRegionResult { double correlation; // Final parameters? + bool used_brute_translation_initialization; }; // Always needs 4 correspondences. @@ -87,8 +103,6 @@ void TrackRegion(const FloatImage &image1, double *x2, double *y2, TrackRegionResult *result); -// TODO(keir): May need a "samplewarp" function. - } // namespace libmv #endif // LIBMV_TRACKING_TRACK_REGION_H_ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index abb45608822..3bf5c735cb7 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -20,6 +20,7 @@ * * Contributor(s): Blender Foundation, * Sergey Sharybin + * Keir Mierle * * ***** END GPL LICENSE BLOCK ***** */ @@ -943,10 +944,14 @@ static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *custo typedef struct TrackContext { #ifdef WITH_LIBMV - float keyframed_pos[2]; + /* the reference marker and cutout search area */ + MovieTrackingMarker marker; - struct libmv_RegionTracker *region_tracker; - float *patch; /* keyframed patch */ + /* keyframed patch. This is the search area */ + float *search_area; + int search_area_height; + int search_area_width; + int framenr; #else int pad; #endif @@ -1011,59 +1016,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u if ((marker->flag & MARKER_DISABLED) == 0) { TrackContext track_context; - memset(&track_context, 0, sizeof(TrackContext)); - -#ifdef WITH_LIBMV - { - float search_size_x, search_size_y; - float pattern_size_x, pattern_size_y; - float pat_min[2], pat_max[2], patx, paty; - float search_to_pattern_ratio, log2_search_to_pattern_ratio; - int wndx, wndy, half_wnd, max_pyramid_levels, level; - - struct libmv_RegionTracker *region_tracker; - - /* XXX: use boundbox of marker's pattern for now - * no idea how it should behave with non-affine tracking */ - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - - patx = (int)((pat_max[0] - pat_min[0]) * width); - paty = (int)((pat_max[1] - pat_min[1]) * height); - wndx = (int)patx / 2; - wndy = (int)paty / 2; - half_wnd = MAX2(wndx, wndy); - - search_size_x = (track->search_max[0] - track->search_min[0]) * width; - search_size_y = (track->search_max[1] - track->search_min[1]) * height; - pattern_size_x = (pat_max[0] - pat_min[0]) * width; - pattern_size_y = (pat_max[1] - pat_min[1]) * height; - - /* compute the maximum pyramid size */ - search_to_pattern_ratio = MIN2(search_size_x, search_size_y) / MAX2(pattern_size_x, pattern_size_y); - log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2; - max_pyramid_levels = floor(log2_search_to_pattern_ratio + 1); - - /* try to accommodate the user's choice of pyramid level in a way - * that doesn't cause the coarsest pyramid pattern to be larger - * than the search size */ - level = MIN2(track->pyramid_levels, max_pyramid_levels); - - if (track->tracker == TRACKER_KLT) { - region_tracker = libmv_pyramidRegionTrackerNew(100, level, half_wnd, - track->minimum_correlation); - } - else if (track->tracker == TRACKER_HYBRID) { - region_tracker = libmv_hybridRegionTrackerNew(100, half_wnd, track->minimum_correlation); - } - else if (track->tracker == TRACKER_SAD) { - region_tracker = libmv_bruteRegionTrackerNew(MAX2(wndx, wndy), track->minimum_correlation); - } - - track_context.region_tracker = region_tracker; - } -#endif - tracks_map_insert(context->tracks_map, track, &track_context); } } @@ -1099,11 +1052,8 @@ static void track_context_free(void *customdata) TrackContext *track_context = (TrackContext *)customdata; #if WITH_LIBMV - if (track_context->region_tracker) - libmv_regionTrackerDestroy(track_context->region_tracker); - - if (track_context->patch) - MEM_freeN(track_context->patch); + if (track_context->search_area) + MEM_freeN(track_context->search_area); #else (void) track_context; @@ -1370,50 +1320,172 @@ ImBuf *BKE_tracking_track_mask_get(MovieTracking *tracking, MovieTrackingTrack * /* Convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue) { int i; - for (i = 0; i < num_pixels; ++i) { + + for (i = 0; i < num_pixels; i++) { const float *pixel = rgba + 4 * i; + gray[i] = weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]; } } static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue) { int i; - for (i = 0; i < num_pixels; ++i) { + + for (i = 0; i < num_pixels; i++) { const unsigned char *pixel = rgba + i * 4; + *gray++ = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f; } } -static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int *width_r, int *height_r, float pos[2], int origin[2]) +static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, int *width_r, int *height_r) { - ImBuf *tmpibuf; + ImBuf *searchibuf; float *gray_pixels; - int x, y, width, height; + int width, height; + /* ignored */ + float pos[2]; + int origin[2]; - width = (track->search_max[0] - track->search_min[0]) * ibuf->x; - height = (track->search_max[1] - track->search_min[1]) * ibuf->y; + searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin); + disable_imbuf_channels(searchibuf, track, FALSE /* don't grayscale */); - tmpibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin); - disable_imbuf_channels(tmpibuf, track, FALSE /* don't grayscale */); + width = searchibuf->x; + height = searchibuf->y; - *width_r = width; - *height_r = height; + *width_r = searchibuf->x; + *height_r = searchibuf->y; gray_pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf"); - if (tmpibuf->rect_float) { - float_rgba_to_gray(tmpibuf->rect_float, gray_pixels, height * width, 0.2126f, 0.7152f, 0.0722f); + if (searchibuf->rect_float) { + float_rgba_to_gray(searchibuf->rect_float, gray_pixels, width * height, 0.2126f, 0.7152f, 0.0722f); } else { - uint8_rgba_to_float_gray((unsigned char *)tmpibuf->rect, gray_pixels, height * width, 0.2126f, 0.7152f, 0.0722f); + uint8_rgba_to_float_gray((unsigned char *)searchibuf->rect, gray_pixels, width * height, 0.2126f, 0.7152f, 0.0722f); } - IMB_freeImBuf(tmpibuf); + IMB_freeImBuf(searchibuf); return gray_pixels; } +/* Three coordinate frames: Frame, Search, and Marker + * Two units: Pixels, Unified + * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search + * window relative coordinates in pixels, and "frame_unified" are unified 0..1 + * coordinates relative to the entire frame. + */ +static void unified_to_pixel(const ImBuf *ibuf, const float unified_coords[2], float pixel_coords[2]) +{ + pixel_coords[0] = unified_coords[0] * ibuf->x; + pixel_coords[1] = unified_coords[1] * ibuf->y; +} + +static void pixel_to_unified(const ImBuf *ibuf, const float pixel_coords[2], float unified_coords[2]) +{ + unified_coords[0] = pixel_coords[0] / ibuf->x; + unified_coords[1] = pixel_coords[1] / ibuf->y; +} + +static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2], float frame_unified_coords[2]) +{ + frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0]; + frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1]; +} + +static void marker_unified_to_frame_pixel_coordinates(const ImBuf *ibuf, const MovieTrackingMarker *marker, + const float marker_unified_coords[2], float frame_pixel_coords[2]) +{ + marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords); + unified_to_pixel(ibuf, frame_pixel_coords, frame_pixel_coords); +} + +static void get_search_origin_frame_pixel(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, float frame_pixel[2]) +{ + /* Get the lower left coordinate of the search window and snap to pixel coordinates */ + marker_unified_to_frame_pixel_coordinates(ibuf, marker, track->search_min, frame_pixel); + frame_pixel[0] = (int)frame_pixel[0]; + frame_pixel[1] = (int)frame_pixel[1]; +} + +static void marker_unified_to_search_pixel(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, + const float marker_unified[2], float search_pixel[2]) +{ + float frame_pixel[2]; + float search_origin_frame_pixel[2]; + marker_unified_to_frame_pixel_coordinates(ibuf, marker, marker_unified, frame_pixel); + get_search_origin_frame_pixel(ibuf, track, marker, search_origin_frame_pixel); + sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel); +} + +static void search_pixel_to_marker_unified(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, + const float search_pixel[2], float marker_unified[2]) +{ + float frame_unified[2]; + float search_origin_frame_pixel[2]; + get_search_origin_frame_pixel(ibuf, track, marker, search_origin_frame_pixel); + add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel); + pixel_to_unified(ibuf, frame_unified, frame_unified); + sub_v2_v2v2(marker_unified, frame_unified, marker->pos /* marker pos is in frame unified */); +} + +/* Each marker has 5 coordinates associated with it that get warped with + * tracking: the four corners ("pattern_corners"), and the cernter ("pos"). + * This function puts those 5 points into the appropriate frame for tracking + * (the "search" coordinate frame). + */ +static void get_marker_coords_for_tracking(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, + double search_pixel_x[5], double search_pixel_y[5]) { + int i; + float unified_coords[2]; + float pixel_coords[2]; + + /* Convert the corners into search space coordinates. */ + for (i = 0; i < 4; ++i) { + marker_unified_to_search_pixel(ibuf, track, marker, marker->pattern_corners[i], pixel_coords); + search_pixel_x[i] = pixel_coords[0]; + search_pixel_y[i] = pixel_coords[1]; + } + /* Convert the center position (aka "pos"); this is the origin */ + unified_coords[0] = 0.0; + unified_coords[1] = 0.0; + marker_unified_to_search_pixel(ibuf, track, marker, unified_coords, pixel_coords); + search_pixel_x[4] = pixel_coords[0]; + search_pixel_y[4] = pixel_coords[1]; +} + +/* Inverse of above. */ +static void set_marker_coords_from_tracking(const ImBuf *ibuf, const MovieTrackingTrack *track, MovieTrackingMarker *marker, + const double search_pixel_x[5], const double search_pixel_y[5]) +{ + int i; + float marker_unified[2]; + float search_pixel[2]; + + /* Convert the corners into search space coordinates. */ + for (i = 0; i < 4; ++i) { + search_pixel[0] = search_pixel_x[i]; + search_pixel[1] = search_pixel_y[i]; + search_pixel_to_marker_unified(ibuf, track, marker, search_pixel, marker->pattern_corners[i]); + } + + /* Convert the center position (aka "pos"); this is the origin */ + search_pixel[0] = search_pixel_x[4]; + search_pixel[1] = search_pixel_y[4]; + search_pixel_to_marker_unified(ibuf, track, marker, search_pixel, marker_unified); + + /* If the tracker tracked nothing, then "marker_unified" would be zero. + * Otherwise, the entire patch shifted, and that delta should be applied to + * all the coordinates. */ + for (i = 0; i < 4; ++i) { + marker->pattern_corners[i][0] -= marker_unified[0]; + marker->pattern_corners[i][1] -= marker_unified[1]; + } + marker->pos[0] += marker_unified[0]; + marker->pos[1] += marker_unified[1]; +} + static unsigned char *get_ucharbuf(ImBuf *ibuf) { int x, y; @@ -1535,7 +1607,7 @@ void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context) int BKE_tracking_next(MovieTrackingContext *context) { - ImBuf *ibuf_new; + ImBuf *destination_ibuf; int curfra = context->user.framenr; int a, ok = FALSE, map_size; @@ -1550,26 +1622,27 @@ int BKE_tracking_next(MovieTrackingContext *context) else context->user.framenr++; - ibuf_new = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag, MOVIECLIP_CACHE_SKIP); - if (!ibuf_new) + destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag, MOVIECLIP_CACHE_SKIP); + if (!destination_ibuf) return FALSE; - #pragma omp parallel for private(a) shared(ibuf_new, ok) if (map_size>1) + #pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size>1) for (a = 0; a < map_size; a++) { TrackContext *track_context = NULL; MovieTrackingTrack *track; MovieTrackingMarker *marker; + double dst_pixel_x[5]; + double dst_pixel_y[5]; + tracks_map_get(context->tracks_map, a, &track, (void**)&track_context); marker = BKE_tracking_exact_marker(track, curfra); if (marker && (marker->flag & MARKER_DISABLED) == 0) { #ifdef WITH_LIBMV - int width, height, origin[2], tracked = 0, need_readjust = 0; - float pos[2], margin[2], dim[2], pat_min[2], pat_max[2]; - double x1, y1, x2, y2; - ImBuf *ibuf = NULL; + int width, height, tracked = 0, need_readjust = 0; + float margin[2], dim[2], pat_min[2], pat_max[2]; MovieTrackingMarker marker_new, *marker_keyed; int onbound = FALSE, nextfra; @@ -1588,8 +1661,8 @@ int BKE_tracking_next(MovieTrackingContext *context) sub_v2_v2v2(dim, pat_max, pat_min); margin[0] = margin[1] = MAX2(dim[0], dim[1]) / 2.0f; - margin[0] = MAX2(margin[0], (float)track->margin / ibuf_new->x); - margin[1] = MAX2(margin[1], (float)track->margin / ibuf_new->y); + margin[0] = MAX2(margin[0], (float)track->margin / destination_ibuf->x); + margin[1] = MAX2(margin[1], (float)track->margin / destination_ibuf->y); /* do not track markers which are too close to boundary */ if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] || @@ -1598,62 +1671,97 @@ int BKE_tracking_next(MovieTrackingContext *context) onbound = TRUE; } else { + /* to convert to the x/y split array format for libmv. */ + double src_pixel_x[5]; + double src_pixel_y[5]; + + /* settings for the tracker */ + struct libmv_trackRegionOptions options; + struct libmv_trackRegionResult result; + float *patch_new; if (need_readjust) { + ImBuf *reference_ibuf = NULL; /* calculate patch for keyframed position */ - ibuf = get_adjust_ibuf(context, track, marker, curfra, &marker_keyed); + reference_ibuf = get_adjust_ibuf(context, track, marker, curfra, &marker_keyed); + track_context->marker = *marker_keyed; - if (track_context->patch) - MEM_freeN(track_context->patch); + if (track_context->search_area) + MEM_freeN(track_context->search_area); - track_context->patch = get_search_floatbuf(ibuf, track, marker_keyed, &width, &height, - track_context->keyframed_pos, origin); + track_context->search_area = get_search_floatbuf(reference_ibuf, track, marker_keyed, &width, &height); + track_context->search_area_height = height; + track_context->search_area_width = width; - IMB_freeImBuf(ibuf); + IMB_freeImBuf(reference_ibuf); } - patch_new = get_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin); + /* XXX for now, the width & height always match because the + * settings are per-track. This will change soon and in that + * case different sizes must be used */ + patch_new = get_search_floatbuf(destination_ibuf, track, marker, &width, &height); - x1 = track_context->keyframed_pos[0]; - y1 = track_context->keyframed_pos[1]; + /* Configure the tracker */ + options.motion_model = 0; + options.num_iterations = 10; + options.minimum_correlation = track->minimum_correlation; + options.sigma = 0.9; - x2 = pos[0]; - y2 = pos[1]; + /* Convert the marker corners and center into pixel coordinates in the search/destination images. */ + printf("track_context: %p\n", track_context); + printf("track_context->marker.framenr: %d\n", track_context->marker.framenr); + printf("marker: %p\n", marker); + printf("marker.framenr: %d\n", marker->framenr); + printf("track: %p\n", track); + printf("destination_ibuf: %p\n", destination_ibuf); + printf("\n"); + get_marker_coords_for_tracking(destination_ibuf, track, &track_context->marker, src_pixel_x, src_pixel_y); + get_marker_coords_for_tracking(destination_ibuf, track, marker, dst_pixel_x, dst_pixel_y); - tracked = libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new, - width, height, x1, y1, &x2, &y2); +#if 1 + /* Run the tracker! */ + tracked = libmv_trackRegion(&options, + track_context->search_area, patch_new, + width, height, + src_pixel_x, src_pixel_y, + &result, + dst_pixel_x, dst_pixel_y); +#else + { + /* XXX: just for debug + * easy to see that marker isn't getting updated properly if it've got + * non-integer initial coordinates */ + int i; + + for (i = 0; i < 5; i++) { + dst_pixel_x[i] = src_pixel_x[i] + 0.5f; + dst_pixel_y[i] = src_pixel_y[i] + 0.5f; + } + + tracked = TRUE; + } +#endif MEM_freeN(patch_new); } - if (tracked && !onbound && finite(x2) && finite(y2)) { + if (tracked && !onbound) { + memset(&marker_new, 0, sizeof(marker_new)); + marker_new = *marker; + set_marker_coords_from_tracking(destination_ibuf, track, &marker_new, dst_pixel_x, dst_pixel_y); + marker_new.flag |= MARKER_TRACKED; + marker_new.framenr = nextfra; + if (context->first_time) { #pragma omp critical { /* check if there's no keyframe/tracked markers before tracking marker. * if so -- create disabled marker before currently tracking "segment" */ - put_disabled_marker(track, marker, !context->backwards, 0); + put_disabled_marker(track, &marker_new, !context->backwards, 0); } } - memset(&marker_new, 0, sizeof(marker_new)); - - if (!onbound) { - marker_new.pos[0] = (origin[0] + x2) / ibuf_new->x; - marker_new.pos[1] = (origin[1] + y2) / ibuf_new->y; - } - else { - copy_v2_v2(marker_new.pos, marker->pos); - } - - /* XXX: currently trackers does not change corners of a track, so - * just copy them from previous position */ - memcpy(marker_new.pattern_corners, marker->pattern_corners, sizeof(marker_new.pattern_corners)); - - marker_new.flag |= MARKER_TRACKED; - marker_new.framenr = nextfra; - #pragma omp critical { BKE_tracking_insert_marker(track, &marker_new); @@ -1682,7 +1790,7 @@ int BKE_tracking_next(MovieTrackingContext *context) } } - IMB_freeImBuf(ibuf_new); + IMB_freeImBuf(destination_ibuf); context->first_time = FALSE; context->frames++; diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index feb77c5c9ec..6f2e017b1f1 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -73,14 +73,16 @@ typedef struct MovieTrackingMarker { /* corners of pattern in the following order: * - * Y - * ^ - * | (3) --- (2) - * | | | - * | | | - * | | | - * | (0) --- (1) - * +-------------> X + * Y + * ^ + * | (3) --- (2) + * | | | + * | | | + * | | | + * | (0) --- (1) + * +-------------> X + * + * the coordinates are stored relative to pos. */ float pattern_corners[4][2]; @@ -95,10 +97,10 @@ typedef struct MovieTrackingTrack { /* ** setings ** */ - /* positions of left-bottom and right-top corners of pattern (in unified 0..1 space) */ + /* positions of left-bottom and right-top corners of pattern (in unified 0..1 units, relative to marker->pos) */ float pat_min[2], pat_max[2] DNA_DEPRECATED; - /* positions of left-bottom and right-top corners of search area (in unified 0..1 space) */ + /* positions of left-bottom and right-top corners of search area (in unified 0..1 units, relative to marker->pos */ float search_min[2], search_max[2]; float offset[2]; /* offset to "parenting" point */ From fddb05024e55c96421f5e0709d981ebab6122095 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 May 2012 12:08:37 +0000 Subject: [PATCH 049/183] use vertex arrays for drawing mask splines --- source/blender/editors/mask/mask_draw.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 68494af684e..e3fe67df16b 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -171,21 +171,12 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceC glPointSize(1.0f); } -static void draw_spline_curve_lines(float *points, int tot_point, int closed) +static void draw_spline_curve_lines(const float *points, int tot_point, int closed) { - int i; - float *fp = points; - - if (closed) - glBegin(GL_LINE_LOOP); - else - glBegin(GL_LINE_STRIP); - - /* MASK_TODO - vertex arrays */ - for (i = 0; i < tot_point; i++, fp += 2) { - glVertex3fv(fp); - } - glEnd(); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, points); + glDrawArrays(closed ? GL_LINE_LOOP : GL_LINE_STRIP, 0, tot_point); + glDisableClientState(GL_VERTEX_ARRAY); } static void draw_dashed_curve(MaskSpline *spline, float *points, int tot_point) From 1670b1ed99fe2d119bb7b62a881330696c7a0008 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 17 May 2012 13:53:20 +0000 Subject: [PATCH 050/183] Remove debug code and clean up sources to match common style used Also made BKE_tracking_get_search_imbuf use space conversion utility functions, so now it's not so annoying that search area calculation is happening differently in different paces. Also allow even sizes for search area. Another small fix is about flipping search area dumping by libmv-capi. It used to be flipped since in blender Y axis is up-aimed. --- extern/libmv/libmv-capi.cpp | 4 +- source/blender/blenkernel/BKE_tracking.h | 3 +- source/blender/blenkernel/intern/tracking.c | 296 +++++++++++--------- 3 files changed, 167 insertions(+), 136 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 7d3dca5c4e8..8894930f3b9 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -239,14 +239,14 @@ static void saveImage(char *prefix, libmv::FloatImage image, int x0, int y0) row_pointers[y]= (png_bytep)malloc(sizeof(png_byte)*4*image.Width()); for (x = 0; x < image.Width(); x++) { - if (x0 == x && y0 == y) { + if (x0 == x && image.Height() - y0 - 1 == y) { row_pointers[y][x*4+0]= 255; row_pointers[y][x*4+1]= 0; row_pointers[y][x*4+2]= 0; row_pointers[y][x*4+3]= 255; } else { - float pixel = image(y, x, 0); + float pixel = image(image.Height() - y - 1, x, 0); row_pointers[y][x*4+0]= pixel*255; row_pointers[y][x*4+1]= pixel*255; row_pointers[y][x*4+2]= pixel*255; diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index f8869bfc74c..6ff1a6e8298 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -75,8 +75,7 @@ struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTra struct MovieTrackingMarker *marker, int margin, int anchored, float pos[2], int origin[2]); struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int margin, int anchored, - float pos[2], int origin[2]); + struct MovieTrackingMarker *marker); struct ImBuf *BKE_tracking_track_mask_get(struct MovieTracking *tracking, struct MovieTrackingTrack *track, int width, int height); void BKE_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 3bf5c735cb7..151881edb34 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -76,6 +76,78 @@ static struct { ListBase tracks; } tracking_clipboard; +/*********************** space transformation functions *************************/ + +/* Three coordinate frames: Frame, Search, and Marker + * Two units: Pixels, Unified + * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search + * window relative coordinates in pixels, and "frame_unified" are unified 0..1 + * coordinates relative to the entire frame. + */ +static void unified_to_pixel(const ImBuf *ibuf, const float unified_coords[2], float pixel_coords[2]) +{ + pixel_coords[0] = unified_coords[0] * ibuf->x; + pixel_coords[1] = unified_coords[1] * ibuf->y; +} + +static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2], + float frame_unified_coords[2]) +{ + frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0]; + frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1]; +} + +static void marker_unified_to_frame_pixel_coordinates(const ImBuf *ibuf, const MovieTrackingMarker *marker, + const float marker_unified_coords[2], float frame_pixel_coords[2]) +{ + marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords); + unified_to_pixel(ibuf, frame_pixel_coords, frame_pixel_coords); +} + +static void get_search_origin_frame_pixel(const ImBuf *ibuf, const MovieTrackingTrack *track, + const MovieTrackingMarker *marker, float frame_pixel[2]) +{ + /* Get the lower left coordinate of the search window and snap to pixel coordinates */ + marker_unified_to_frame_pixel_coordinates(ibuf, marker, track->search_min, frame_pixel); + frame_pixel[0] = (int)frame_pixel[0]; + frame_pixel[1] = (int)frame_pixel[1]; +} + +#ifdef WITH_LIBMV +static void pixel_to_unified(const ImBuf *ibuf, const float pixel_coords[2], float unified_coords[2]) +{ + unified_coords[0] = pixel_coords[0] / ibuf->x; + unified_coords[1] = pixel_coords[1] / ibuf->y; +} + +static void marker_unified_to_search_pixel(const ImBuf *ibuf, const MovieTrackingTrack *track, + const MovieTrackingMarker *marker, const float marker_unified[2], + float search_pixel[2]) +{ + float frame_pixel[2]; + float search_origin_frame_pixel[2]; + + marker_unified_to_frame_pixel_coordinates(ibuf, marker, marker_unified, frame_pixel); + get_search_origin_frame_pixel(ibuf, track, marker, search_origin_frame_pixel); + sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel); +} + +static void search_pixel_to_marker_unified(const ImBuf *ibuf, const MovieTrackingTrack *track, + const MovieTrackingMarker *marker, const float search_pixel[2], + float marker_unified[2]) +{ + float frame_unified[2]; + float search_origin_frame_pixel[2]; + + get_search_origin_frame_pixel(ibuf, track, marker, search_origin_frame_pixel); + add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel); + pixel_to_unified(ibuf, frame_unified, frame_unified); + + /* marker pos is in frame unified */ + sub_v2_v2v2(marker_unified, frame_unified, marker->pos); +} +#endif + /*********************** common functions *************************/ void BKE_tracking_init_settings(MovieTracking *tracking) @@ -114,7 +186,8 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) } /* XXX: currently search area is global, pattern size is per-marker, so we'll need to - * find maximal size of pattern to clamp search size nicely */ + * find maximal size of pattern to clamp search size nicely + */ INIT_MINMAX2(pat_min, pat_max); for (a = 0; a < track->markersnr; a++) { @@ -127,7 +200,8 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) } /* compute the effective pattern size, which differs from the fine resolution - * pattern size for the pyramid KLT tracker */ + * pattern size for the pyramid KLT tracker + */ for (a = 0; a < 2; a++) { eff_pat_min[a] = max_pyramid_level_factor * pat_min[a]; eff_pat_max[a] = max_pyramid_level_factor * pat_max[a]; @@ -147,7 +221,8 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) #if 0 /* XXX: needs porting, but we need to know marker here, will be ported after a bit - * more global refactoring */ + * more global refactoring + */ for (a = 0; a < 2; a++) { /* pattern shouldn't be moved outside of search */ if (eff_pat_min[a] < track->search_min[a]) { @@ -192,7 +267,8 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) float search_ratio = 2.3f * max_pyramid_level_factor; /* resize the search area to something sensible based - * on the number of pyramid levels */ + * on the number of pyramid levels + */ for (a = 0; a < 2; a++) { track->search_min[a] = search_ratio * pat_min[a]; track->search_max[a] = search_ratio * pat_max[a]; @@ -542,7 +618,8 @@ void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) { /* both tracks are enabled on this frame, so find the whole segment * on which tracks are intersecting and blend tracks using linear - * interpolation to prevent jumps */ + * interpolation to prevent jumps + */ MovieTrackingMarker *marker_a, *marker_b; int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr; @@ -842,7 +919,8 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) /* duplicate currently operating tracks to temporary list. * this is needed to keep names in unique state and it's faster to change names - * of currently operating tracks (if needed) */ + * of currently operating tracks (if needed) + */ for (a = 0; a < map->num_tracks; a++) { int replace_sel = 0, replace_rot = 0; MovieTrackingTrack *new_track, *old; @@ -1034,7 +1112,8 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u * would be used for images * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might * be stored in a different location - * ignore all the rest possible flags for now */ + * ignore all the rest possible flags for now + */ context->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS; context->user = *user; @@ -1072,7 +1151,8 @@ void BKE_tracking_context_free(MovieTrackingContext *context) /* zap channels from the imbuf that are disabled by the user. this can lead to * better tracks sometimes. however, instead of simply zeroing the channels - * out, do a partial grayscale conversion so the display is better. */ + * out, do a partial grayscale conversion so the display is better. + */ void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, int grayscale) { @@ -1083,7 +1163,8 @@ void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disab return; /* If only some components are selected, it's important to rescale the result - * appropriately so that e.g. if only blue is selected, it's not zeroed out. */ + * appropriately so that e.g. if only blue is selected, it's not zeroed out. + */ scale = (disable_red ? 0.0f : 0.2126f) + (disable_green ? 0.0f : 0.7152f) + (disable_blue ? 0.0f : 0.0722f); @@ -1203,16 +1284,41 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo float pat_min[2], pat_max[2]; /* XXX: need to do real quad sampling here, but currently just assume - * corners represents quad pattern */ + * corners represents quad pattern + */ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, margin, anchored, pos, origin); } -ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int margin, int anchored, float pos[2], int origin[2]) +ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker) { - return get_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin); + ImBuf *searchibuf; + int x, y, w, h; + float search_origin[2]; + + get_search_origin_frame_pixel(ibuf, track, marker, search_origin); + + x = search_origin[0]; + y = search_origin[1]; + + w = (track->search_max[0] - track->search_min[0]) * ibuf->x; + h = (track->search_max[1] - track->search_min[1]) * ibuf->y; + + searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); + searchibuf->profile = ibuf->profile; + + IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); + + if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || + (track->flag & TRACK_DISABLE_RED) || + (track->flag & TRACK_DISABLE_GREEN) || + (track->flag & TRACK_DISABLE_BLUE)) + { + disable_imbuf_channels(searchibuf, track, FALSE); + } + + return searchibuf; } static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track) @@ -1295,13 +1401,9 @@ ImBuf *BKE_tracking_track_mask_get(MovieTracking *tracking, MovieTrackingTrack * bGPDlayer *layer = track_mask_gpencil_layer_get(track); int mask_width, mask_height; - /* XXX: currently copied from get_area_ibuf */ mask_width = (track->search_max[0] - track->search_min[0]) * width; mask_height = (track->search_max[1] - track->search_min[1]) * height; - mask_width = mask_width | 1; - mask_height = mask_height | 1; - ibuf = IMB_allocImBuf(mask_width, mask_height, 32, IB_rect | IB_rectfloat); if (layer) { @@ -1318,7 +1420,9 @@ ImBuf *BKE_tracking_track_mask_get(MovieTracking *tracking, MovieTrackingTrack * #ifdef WITH_LIBMV /* Convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ -static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue) { +static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels, + float weight_red, float weight_green, float weight_blue) +{ int i; for (i = 0; i < num_pixels; i++) { @@ -1328,7 +1432,9 @@ static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels, f } } -static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue) { +static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int num_pixels, + float weight_red, float weight_green, float weight_blue) +{ int i; for (i = 0; i < num_pixels; i++) { @@ -1338,17 +1444,14 @@ static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int } } -static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, int *width_r, int *height_r) +static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int *width_r, int *height_r) { ImBuf *searchibuf; float *gray_pixels; int width, height; - /* ignored */ - float pos[2]; - int origin[2]; - searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin); - disable_imbuf_channels(searchibuf, track, FALSE /* don't grayscale */); + searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker); width = searchibuf->x; height = searchibuf->y; @@ -1359,10 +1462,12 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT gray_pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf"); if (searchibuf->rect_float) { - float_rgba_to_gray(searchibuf->rect_float, gray_pixels, width * height, 0.2126f, 0.7152f, 0.0722f); + float_rgba_to_gray(searchibuf->rect_float, gray_pixels, width * height, + 0.2126f, 0.7152f, 0.0722f); } else { - uint8_rgba_to_float_gray((unsigned char *)searchibuf->rect, gray_pixels, width * height, 0.2126f, 0.7152f, 0.0722f); + uint8_rgba_to_float_gray((unsigned char *)searchibuf->rect, gray_pixels, width * height, + 0.2126f, 0.7152f, 0.0722f); } IMB_freeImBuf(searchibuf); @@ -1370,79 +1475,21 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT return gray_pixels; } -/* Three coordinate frames: Frame, Search, and Marker - * Two units: Pixels, Unified - * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search - * window relative coordinates in pixels, and "frame_unified" are unified 0..1 - * coordinates relative to the entire frame. - */ -static void unified_to_pixel(const ImBuf *ibuf, const float unified_coords[2], float pixel_coords[2]) -{ - pixel_coords[0] = unified_coords[0] * ibuf->x; - pixel_coords[1] = unified_coords[1] * ibuf->y; -} - -static void pixel_to_unified(const ImBuf *ibuf, const float pixel_coords[2], float unified_coords[2]) -{ - unified_coords[0] = pixel_coords[0] / ibuf->x; - unified_coords[1] = pixel_coords[1] / ibuf->y; -} - -static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2], float frame_unified_coords[2]) -{ - frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0]; - frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1]; -} - -static void marker_unified_to_frame_pixel_coordinates(const ImBuf *ibuf, const MovieTrackingMarker *marker, - const float marker_unified_coords[2], float frame_pixel_coords[2]) -{ - marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords); - unified_to_pixel(ibuf, frame_pixel_coords, frame_pixel_coords); -} - -static void get_search_origin_frame_pixel(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, float frame_pixel[2]) -{ - /* Get the lower left coordinate of the search window and snap to pixel coordinates */ - marker_unified_to_frame_pixel_coordinates(ibuf, marker, track->search_min, frame_pixel); - frame_pixel[0] = (int)frame_pixel[0]; - frame_pixel[1] = (int)frame_pixel[1]; -} - -static void marker_unified_to_search_pixel(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, - const float marker_unified[2], float search_pixel[2]) -{ - float frame_pixel[2]; - float search_origin_frame_pixel[2]; - marker_unified_to_frame_pixel_coordinates(ibuf, marker, marker_unified, frame_pixel); - get_search_origin_frame_pixel(ibuf, track, marker, search_origin_frame_pixel); - sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel); -} - -static void search_pixel_to_marker_unified(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, - const float search_pixel[2], float marker_unified[2]) -{ - float frame_unified[2]; - float search_origin_frame_pixel[2]; - get_search_origin_frame_pixel(ibuf, track, marker, search_origin_frame_pixel); - add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel); - pixel_to_unified(ibuf, frame_unified, frame_unified); - sub_v2_v2v2(marker_unified, frame_unified, marker->pos /* marker pos is in frame unified */); -} - /* Each marker has 5 coordinates associated with it that get warped with * tracking: the four corners ("pattern_corners"), and the cernter ("pos"). * This function puts those 5 points into the appropriate frame for tracking * (the "search" coordinate frame). */ -static void get_marker_coords_for_tracking(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, - double search_pixel_x[5], double search_pixel_y[5]) { +static void get_marker_coords_for_tracking(const ImBuf *ibuf, const MovieTrackingTrack *track, + const MovieTrackingMarker *marker, + double search_pixel_x[5], double search_pixel_y[5]) +{ int i; float unified_coords[2]; float pixel_coords[2]; /* Convert the corners into search space coordinates. */ - for (i = 0; i < 4; ++i) { + for (i = 0; i < 4; i++) { marker_unified_to_search_pixel(ibuf, track, marker, marker->pattern_corners[i], pixel_coords); search_pixel_x[i] = pixel_coords[0]; search_pixel_y[i] = pixel_coords[1]; @@ -1451,20 +1498,22 @@ static void get_marker_coords_for_tracking(const ImBuf *ibuf, const MovieTrackin unified_coords[0] = 0.0; unified_coords[1] = 0.0; marker_unified_to_search_pixel(ibuf, track, marker, unified_coords, pixel_coords); + search_pixel_x[4] = pixel_coords[0]; search_pixel_y[4] = pixel_coords[1]; } /* Inverse of above. */ -static void set_marker_coords_from_tracking(const ImBuf *ibuf, const MovieTrackingTrack *track, MovieTrackingMarker *marker, - const double search_pixel_x[5], const double search_pixel_y[5]) +static void set_marker_coords_from_tracking(const ImBuf *ibuf, const MovieTrackingTrack *track, + MovieTrackingMarker *marker, const double search_pixel_x[5], + const double search_pixel_y[5]) { int i; float marker_unified[2]; float search_pixel[2]; /* Convert the corners into search space coordinates. */ - for (i = 0; i < 4; ++i) { + for (i = 0; i < 4; i++) { search_pixel[0] = search_pixel_x[i]; search_pixel[1] = search_pixel_y[i]; search_pixel_to_marker_unified(ibuf, track, marker, search_pixel, marker->pattern_corners[i]); @@ -1477,11 +1526,13 @@ static void set_marker_coords_from_tracking(const ImBuf *ibuf, const MovieTracki /* If the tracker tracked nothing, then "marker_unified" would be zero. * Otherwise, the entire patch shifted, and that delta should be applied to - * all the coordinates. */ - for (i = 0; i < 4; ++i) { + * all the coordinates. + */ + for (i = 0; i < 4; i++) { marker->pattern_corners[i][0] -= marker_unified[0]; marker->pattern_corners[i][1] -= marker_unified[1]; } + marker->pos[0] += marker_unified[0]; marker->pos[1] += marker_unified[1]; } @@ -1622,7 +1673,8 @@ int BKE_tracking_next(MovieTrackingContext *context) else context->user.framenr++; - destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag, MOVIECLIP_CACHE_SKIP); + destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, + context->clip_flag, MOVIECLIP_CACHE_SKIP); if (!destination_ibuf) return FALSE; @@ -1632,10 +1684,7 @@ int BKE_tracking_next(MovieTrackingContext *context) MovieTrackingTrack *track; MovieTrackingMarker *marker; - double dst_pixel_x[5]; - double dst_pixel_y[5]; - - tracks_map_get(context->tracks_map, a, &track, (void**)&track_context); + tracks_map_get(context->tracks_map, a, &track, (void **)&track_context); marker = BKE_tracking_exact_marker(track, curfra); @@ -1645,6 +1694,7 @@ int BKE_tracking_next(MovieTrackingContext *context) float margin[2], dim[2], pat_min[2], pat_max[2]; MovieTrackingMarker marker_new, *marker_keyed; int onbound = FALSE, nextfra; + double dst_pixel_x[5], dst_pixel_y[5]; if (track->pattern_match == TRACK_MATCH_KEYFRAME) need_readjust = context->first_time; @@ -1690,16 +1740,17 @@ int BKE_tracking_next(MovieTrackingContext *context) if (track_context->search_area) MEM_freeN(track_context->search_area); - track_context->search_area = get_search_floatbuf(reference_ibuf, track, marker_keyed, &width, &height); + track_context->search_area = get_search_floatbuf(reference_ibuf, track, + marker_keyed, &width, &height); track_context->search_area_height = height; track_context->search_area_width = width; IMB_freeImBuf(reference_ibuf); } - /* XXX for now, the width & height always match because the - * settings are per-track. This will change soon and in that - * case different sizes must be used */ + /* XXX: for now, the width & height always match because the + * settings are per-track. This will change soon and in that + * case different sizes must be used */ patch_new = get_search_floatbuf(destination_ibuf, track, marker, &width, &height); /* Configure the tracker */ @@ -1709,17 +1760,12 @@ int BKE_tracking_next(MovieTrackingContext *context) options.sigma = 0.9; /* Convert the marker corners and center into pixel coordinates in the search/destination images. */ - printf("track_context: %p\n", track_context); - printf("track_context->marker.framenr: %d\n", track_context->marker.framenr); - printf("marker: %p\n", marker); - printf("marker.framenr: %d\n", marker->framenr); - printf("track: %p\n", track); - printf("destination_ibuf: %p\n", destination_ibuf); - printf("\n"); - get_marker_coords_for_tracking(destination_ibuf, track, &track_context->marker, src_pixel_x, src_pixel_y); - get_marker_coords_for_tracking(destination_ibuf, track, marker, dst_pixel_x, dst_pixel_y); + get_marker_coords_for_tracking(destination_ibuf, track, &track_context->marker, + src_pixel_x, src_pixel_y); + + get_marker_coords_for_tracking(destination_ibuf, track, marker, + dst_pixel_x, dst_pixel_y); -#if 1 /* Run the tracker! */ tracked = libmv_trackRegion(&options, track_context->search_area, patch_new, @@ -1727,22 +1773,6 @@ int BKE_tracking_next(MovieTrackingContext *context) src_pixel_x, src_pixel_y, &result, dst_pixel_x, dst_pixel_y); -#else - { - /* XXX: just for debug - * easy to see that marker isn't getting updated properly if it've got - * non-integer initial coordinates */ - int i; - - for (i = 0; i < 5; i++) { - dst_pixel_x[i] = src_pixel_x[i] + 0.5f; - dst_pixel_y[i] = src_pixel_y[i] + 0.5f; - } - - tracked = TRUE; - } -#endif - MEM_freeN(patch_new); } @@ -1757,7 +1787,8 @@ int BKE_tracking_next(MovieTrackingContext *context) #pragma omp critical { /* check if there's no keyframe/tracked markers before tracking marker. - * if so -- create disabled marker before currently tracking "segment" */ + * if so -- create disabled marker before currently tracking "segment" + */ put_disabled_marker(track, &marker_new, !context->backwards, 0); } } @@ -3013,7 +3044,8 @@ ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, if (tangle == 0.0f) { /* if angle is zero, then it's much faster to use rect copy - * but could be issues with subpixel precisions */ + * but could be issues with subpixel precisions + */ IMB_rectcpy(tmpibuf, ibuf, tloc[0] - (tscale - 1.0f) * width / 2.0f, tloc[1] - (tscale - 1.0f) * height / 2.0f, From 81016d59b63b5e5231ea99c5b8ccce55985de851 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 May 2012 15:01:51 +0000 Subject: [PATCH 051/183] fix for building without aud --- source/blender/makesrna/intern/rna_sequencer_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 41c6f046c04..3825bc35d3a 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -213,8 +213,8 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor return seq; } #else /* WITH_AUDASPACE */ -static Sequence *rna_Sequences_new_sound(ID *UNUSED(id), Editing *UNUSED(ed), bMain *UNUSED(main), ReportList *UNUSED(reports), - const char *UNUSED(name), bSound *UNUSED(sound), int UNUSED(channel), int UNUSED(start_frame)) +static Sequence *rna_Sequences_new_sound(ID *UNUSED(id), Editing *UNUSED(ed), Main *UNUSED(bmain), ReportList *reports, + const char *UNUSED(name), const char *UNUSED(file), int UNUSED(channel), int UNUSED(start_frame)) { BKE_report(reports, RPT_ERROR, "Blender compiled without Audaspace support."); return NULL; From 892888ec64ebc7e939d07ced841202749331d9e9 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Thu, 17 May 2012 15:52:56 +0000 Subject: [PATCH 052/183] Adds basic curves with holes support for multi-spline mask curves. --- intern/raskter/raskter.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index b80b7de379b..f9c2f851f6e 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -302,7 +302,13 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) mpxl = spxl + MIN2(e_curr->x, rb.sizex) - 1; /* draw the pixels. */ - for (; cpxl <= mpxl; *cpxl++ = 1.0f) ; + for (; cpxl <= mpxl; cpxl++){ + if(*cpxl < 0.5f){ + *cpxl = 1.0f; + }else{ + *cpxl = 0.0f; + } + } } /* From 9932bb1dd6b2c9e4d7ae0c5753857605a25d8e24 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 17 May 2012 16:45:02 +0000 Subject: [PATCH 053/183] Tomato: sliding corner with Ctrl holded down would have scaling behavior --- .../blender/editors/space_clip/tracking_ops.c | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 89b14b06220..b072b7475ac 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -264,7 +264,7 @@ typedef struct { float smin[2], smax[2], spos[2], soff[2], scorners[4][2]; float (*smarkers)[2]; - int lock, accurate; + int lock, accurate, scale; } SlideMarkerData; static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTrack *track, @@ -636,6 +636,10 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) data->lock = event->val == KM_RELEASE; + if (data->action == SLIDE_ACTION_POS) + if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) + data->scale = event->val == KM_PRESS; + if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) data->accurate = event->val == KM_PRESS; @@ -718,15 +722,31 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) BKE_tracking_clamp_track(data->track, CLAMP_SEARCH_POS); } else if (data->action == SLIDE_ACTION_POS) { - float spos[2]; + if (data->scale) { + float scale = 1.0f + 10.0f * (dx - dy); - copy_v2_v2(spos, data->pos); + if (scale > 0.0f) { + int a; - data->pos[0] = data->spos[0] + dx; - data->pos[1] = data->spos[1] + dy; + for (a = 0; a < 4; a++) { + mul_v2_v2fl(data->corners[a], data->scorners[a], scale); + } + } + } + else { + float spos[2]; - if (!slide_check_corners(data->corners)) { - copy_v2_v2(data->pos, spos); + copy_v2_v2(spos, data->pos); + + /* corners might've been scaled before, restore their original position */ + memcpy(data->corners, data->scorners, sizeof(data->scorners)); + + data->pos[0] = data->spos[0] + dx; + data->pos[1] = data->spos[1] + dy; + + if (!slide_check_corners(data->corners)) { + copy_v2_v2(data->pos, spos); + } } /* currently only patterns are allowed to have such combination of event and data */ From 82e45dd275205c84a72ba9aedac0bdc4f04e055a Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Thu, 17 May 2012 17:09:51 +0000 Subject: [PATCH 054/183] Add panels for the new planar tracker This replaces the old style tracker configuration panel with the new planar tracking panel. From a users perspective, this means: - The old "tracking algorithm" picker is gone. There is only 1 algorithm now. We may revisit this later, but I would much prefer to have only 1 algorithm. So far no optimization work has been done so the speed is not there yet. - There is now a dropdown to select the motion model. Choices: * Translation * Translation, rotation * Translation, scale * Translation, rotation, scale * Affine (Not implemented yet) * Perspective The most stable is the "translation" parameterization. The others work but still require some tweaking. - The old "Hybrid" mode is gone; instead there is a toggle to enable or disable translation-only tracker initialization. This is the equivalent of the hyrbid mode before, but rewritten to work with the new planar tracking modes. - The pyramid levels setting is gone. At a future date, the planar tracker will decide to use pyramids or not automatically. The pyramid setting was ultimately a mistake; with the brute force initialization it is unnecessary. --- extern/libmv/libmv-capi.cpp | 1 + extern/libmv/libmv-capi.h | 1 + extern/libmv/libmv/tracking/track_region.cc | 5 +- release/scripts/startup/bl_ui/space_clip.py | 12 +- source/blender/blenkernel/BKE_tracking.h | 1 - source/blender/blenkernel/intern/tracking.c | 44 ++---- source/blender/blenloader/intern/readfile.c | 8 +- source/blender/editors/space_clip/clip_draw.c | 45 ------ source/blender/makesdna/DNA_tracking_types.h | 43 +++--- source/blender/makesrna/intern/rna_tracking.c | 134 ++++++------------ 10 files changed, 89 insertions(+), 205 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 8894930f3b9..482a4c98245 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -380,6 +380,7 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options, track_region_options.sigma = options->sigma; track_region_options.num_extra_points = 1; track_region_options.image1_mask = NULL; + track_region_options.use_brute_initialization = options->use_brute; /* Convert from raw float buffers to libmv's FloatImage. */ libmv::FloatImage old_patch, new_patch; diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index d3f02f99e51..9fedb9b9683 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -54,6 +54,7 @@ void libmv_regionTrackerDestroy(struct libmv_RegionTracker *libmv_tracker); struct libmv_trackRegionOptions { int motion_model; int num_iterations; + int use_brute; double minimum_correlation; double sigma; }; diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index 0dac56aeff7..22c86a7f5b9 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -499,7 +499,7 @@ struct TranslationRotationWarp { q2.CornerRelativeToCentroid(i).transpose(); } Mat2 R = OrthogonalProcrustes(correlation_matrix); - parameters[2] = acos(R(0, 0)); + parameters[2] = atan2(R(1, 0), R(0, 0)); std::cout << "correlation_matrix:\n" << correlation_matrix << "\n"; std::cout << "R:\n" << R << "\n"; @@ -575,7 +575,7 @@ struct TranslationRotationScaleWarp { std::cout << "correlation_matrix:\n" << correlation_matrix << "\n"; Mat2 R = OrthogonalProcrustes(correlation_matrix); std::cout << "R:\n" << R << "\n"; - parameters[3] = acos(R(0, 0)); + parameters[3] = atan2(R(1, 0), R(0, 0)); std::cout << "theta:" << parameters[3] << "\n"; } @@ -949,6 +949,7 @@ void TemplatedTrackRegion(const FloatImage &image1, // TODO(keir): Consider removing these options before committing. solver_options.numeric_derivative_relative_step_size = 1e-3; + solver_options.check_gradients = false; solver_options.gradient_check_relative_precision = 1e-10; solver_options.minimizer_progress_to_stdout = false; diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 358c534a3a7..c17266cf303 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -187,10 +187,8 @@ class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel): sub.prop(settings, "default_search_size") col.label(text="Tracker:") - col.prop(settings, "default_tracker", text="") - - if settings.default_tracker == 'KLT': - col.prop(settings, "default_pyramid_levels") + col.prop(settings, "default_motion_model") + col.prop(settings, "default_use_brute") col.prop(settings, "default_correlation_min") col.separator() @@ -488,10 +486,8 @@ class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel): active = clip.tracking.tracks.active if active: - col.prop(active, "tracker") - - if active.tracker == 'KLT': - col.prop(active, "pyramid_levels") + col.prop(active, "motion_model") + col.prop(active, "use_brute") col.prop(active, "correlation_min") col.separator() diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 6ff1a6e8298..4b94fcb7260 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -190,7 +190,6 @@ void BKE_tracking_dopesheet_update(struct MovieTracking *tracking, int sort_meth #define CLAMP_PAT_POS 2 #define CLAMP_SEARCH_DIM 3 #define CLAMP_SEARCH_POS 4 -#define CLAMP_PYRAMID_LEVELS 5 #define TRACK_AREA_NONE -1 #define TRACK_AREA_POINT 1 diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 151881edb34..1956492fce9 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -156,11 +156,10 @@ void BKE_tracking_init_settings(MovieTracking *tracking) tracking->camera.pixel_aspect = 1.0f; tracking->camera.units = CAMERA_UNITS_MM; - tracking->settings.default_tracker = TRACKER_HYBRID; + tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION; tracking->settings.default_minimum_correlation = 0.75; tracking->settings.default_pattern_size = 11; tracking->settings.default_search_size = 61; - tracking->settings.default_pyramid_levels = 2; tracking->settings.keyframe1 = 1; tracking->settings.keyframe2 = 30; tracking->settings.dist = 1; @@ -179,11 +178,6 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) int a; float pat_min[2], pat_max[2]; float eff_pat_min[2], eff_pat_max[2]; - float max_pyramid_level_factor = 1.0; - - if (track->tracker == TRACKER_KLT) { - max_pyramid_level_factor = 1 << (track->pyramid_levels - 1); - } /* XXX: currently search area is global, pattern size is per-marker, so we'll need to * find maximal size of pattern to clamp search size nicely @@ -199,13 +193,8 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) DO_MINMAX2(cur_pat_max, pat_min, pat_max); } - /* compute the effective pattern size, which differs from the fine resolution - * pattern size for the pyramid KLT tracker - */ - for (a = 0; a < 2; a++) { - eff_pat_min[a] = max_pyramid_level_factor * pat_min[a]; - eff_pat_max[a] = max_pyramid_level_factor * pat_max[a]; - } + copy_v2_v2(eff_pat_min, pat_min); + copy_v2_v2(eff_pat_max, pat_max); if (event == CLAMP_PAT_DIM) { for (a = 0; a < 2; a++) { @@ -260,19 +249,12 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) } } } - else if (event == CLAMP_PYRAMID_LEVELS || (event == CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT)) { + else if (event == CLAMP_SEARCH_DIM) { float dim[2]; sub_v2_v2v2(dim, pat_max, pat_min); - { - float search_ratio = 2.3f * max_pyramid_level_factor; - - /* resize the search area to something sensible based - * on the number of pyramid levels - */ - for (a = 0; a < 2; a++) { - track->search_min[a] = search_ratio * pat_min[a]; - track->search_max[a] = search_ratio * pat_max[a]; - } + for (a = 0; a < 2; a++) { + track->search_min[a] = pat_min[a]; + track->search_max[a] = pat_max[a]; } } } @@ -320,13 +302,13 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr track = MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track"); strcpy(track->name, "Track"); - track->tracker = settings->default_tracker; - track->pyramid_levels = settings->default_pyramid_levels; + track->motion_model = settings->default_motion_model; track->minimum_correlation = settings->default_minimum_correlation; track->margin = settings->default_margin; track->pattern_match = settings->default_pattern_match; track->frames_limit = settings->default_frames_limit; track->flag = settings->default_flag; + track->algorithm_flag = settings->default_algorithm_flag; memset(&marker, 0, sizeof(marker)); marker.pos[0] = x; @@ -347,9 +329,6 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr BKE_tracking_insert_marker(track, &marker); - if (track->tracker == TRACKER_KLT) - BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS); - BLI_addtail(tracksbase, track); BKE_track_unique_name(tracksbase, track); @@ -1754,8 +1733,9 @@ int BKE_tracking_next(MovieTrackingContext *context) patch_new = get_search_floatbuf(destination_ibuf, track, marker, &width, &height); /* Configure the tracker */ - options.motion_model = 0; - options.num_iterations = 10; + options.motion_model = track->motion_model; + options.use_brute = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) == 0); + options.num_iterations = 50; options.minimum_correlation = track->minimum_correlation; options.sigma = 0.9; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 3e3d24d7281..bb944eaf429 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7122,9 +7122,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) track= clip->tracking.tracks.first; while (track) { - if (track->pyramid_levels==0) - track->pyramid_levels= 2; - if (track->minimum_correlation==0.0f) track->minimum_correlation= 0.75f; @@ -7146,9 +7143,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (clip= main->movieclip.first; clip; clip= clip->id.next) { MovieTrackingSettings *settings= &clip->tracking.settings; - if (settings->default_pyramid_levels==0) { - settings->default_tracker= TRACKER_KLT; - settings->default_pyramid_levels= 2; + if (settings->default_pattern_size == 0.0f) { + settings->default_motion_model= TRACK_MOTION_MODEL_TRANSLATION; settings->default_minimum_correlation= 0.75; settings->default_pattern_size= 11; settings->default_search_size= 51; diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index aa9af704280..a06da289326 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -668,51 +668,6 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra glEnd(); } - /* pyramid */ - if (sel && TRACK_VIEW_SELECTED(sc, track) && - (track->tracker == TRACKER_KLT) && - (marker->flag & MARKER_DISABLED) == 0) - { - if (track->flag & TRACK_LOCKED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else if (track->pat_flag & SELECT) - UI_ThemeColorShade(TH_LOCK_MARKER, 64); - else UI_ThemeColor(TH_LOCK_MARKER); - } - else if (marker->flag & MARKER_DISABLED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else if (track->pat_flag & SELECT) - UI_ThemeColorShade(TH_DIS_MARKER, 128); - else UI_ThemeColor(TH_DIS_MARKER); - } - else { - if (track->pat_flag & SELECT) - glColor3fv(scol); - else - glColor3fv(col); - } - - { - int i = 0; - glPushMatrix(); - glEnable(GL_LINE_STIPPLE); - for (i = 1; i < track->pyramid_levels; ++i) { - glScalef(2.0f, 2.0f, 1.0); - } - /* only draw a pattern for the coarsest level */ - glBegin(GL_LINE_LOOP); - glVertex2fv(marker->pattern_corners[0]); - glVertex2fv(marker->pattern_corners[1]); - glVertex2fv(marker->pattern_corners[2]); - glVertex2fv(marker->pattern_corners[3]); - glEnd(); - glDisable(GL_LINE_STIPPLE); - glPopMatrix(); - } - } - if (tiny) glDisable(GL_LINE_STIPPLE); diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 6f2e017b1f1..f15bf4ba8d8 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -118,17 +118,14 @@ typedef struct MovieTrackingTrack { int flag, pat_flag, search_flag; /* flags (selection, ...) */ float color[3]; /* custom color for track */ - /* tracking algorithm to use; can be KLT or SAD */ + /* ** control how tracking happens */ short frames_limit; /* number of frames to be tarcked during single tracking session (if TRACKING_FRAMES_LIMIT is set) */ short margin; /* margin from frame boundaries */ short pattern_match; /* re-adjust every N frames */ - short tracker; /* tracking algorithm used for this track */ - - /* ** KLT tracker settings ** */ - short pyramid_levels, pad2; /* number of pyramid levels to use for KLT tracking */ - - /* ** SAD tracker settings ** */ + /* tracking parameters */ + short motion_model; /* model of the motion for this track */ + int algorithm_flag; /* flags for the tracking algorithm (use brute, use esm, use pyramid, etc */ float minimum_correlation; /* minimal correlation which is still treated as successful tracking */ struct bGPdata *gpd; /* grease-pencil data */ @@ -138,15 +135,15 @@ typedef struct MovieTrackingSettings { int flag; /* ** default tracker settings */ - short default_tracker; /* tracking algorithm used by default */ - short default_pyramid_levels; /* number of pyramid levels to use for KLT tracking */ - float default_minimum_correlation; /* minimal correlation which is still treated as successful tracking */ - short default_pattern_size; /* size of pattern area for new tracks */ - short default_search_size; /* size of search area for new tracks */ - short default_frames_limit; /* number of frames to be tarcked during single tracking session (if TRACKING_FRAMES_LIMIT is set) */ - short default_margin; /* margin from frame boundaries */ - short default_pattern_match; /* re-adjust every N frames */ - short default_flag; /* default flags like color channels used by default */ + short default_motion_model; /* model of the motion for this track */ + short default_algorithm_flag; /* flags for the tracking algorithm (use brute, use esm, use pyramid, etc */ + float default_minimum_correlation; /* minimal correlation which is still treated as successful tracking */ + short default_pattern_size; /* size of pattern area for new tracks */ + short default_search_size; /* size of search area for new tracks */ + short default_frames_limit; /* number of frames to be tarcked during single tracking session (if TRACKING_FRAMES_LIMIT is set) */ + short default_margin; /* margin from frame boundaries */ + short default_pattern_match; /* re-adjust every N frames */ + short default_flag; /* default flags like color channels used by default */ short motion_flag; /* flags describes motion type */ @@ -280,10 +277,16 @@ enum { #define TRACK_PREVIEW_GRAYSCALE (1<<9) #define TRACK_DOPE_SEL (1<<10) -/* MovieTrackingTrack->tracker */ -#define TRACKER_KLT 0 -#define TRACKER_SAD 1 -#define TRACKER_HYBRID 2 +/* MovieTrackingTrack->motion_model */ +#define TRACK_MOTION_MODEL_TRANSLATION 0 +#define TRACK_MOTION_MODEL_TRANSLATION_ROTATION 1 +#define TRACK_MOTION_MODEL_TRANSLATION_SCALE 2 +#define TRACK_MOTION_MODEL_TRANSLATION_ROTATION_SCALE 3 +#define TRACK_MOTION_MODEL_AFFINE 4 +#define TRACK_MOTION_MODEL_HOMOGRAPHY 5 + +/* MovieTrackingTrack->algorithm_flag */ +#define TRACK_ALGORITHM_FLAG_USE_BRUTE 0 /* MovieTrackingTrack->adjframes */ #define TRACK_MATCH_KEYFRAME 0 diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 9f5dc75506b..34dd471e9c1 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -59,20 +59,6 @@ static char *rna_tracking_path(PointerRNA *UNUSED(ptr)) return BLI_sprintfN("tracking"); } -static void rna_tracking_defaultSettings_levelsUpdate(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieClip *clip = (MovieClip*)ptr->id.data; - MovieTracking *tracking = &clip->tracking; - MovieTrackingSettings *settings = &tracking->settings; - - if (settings->default_tracker == TRACKER_KLT) { - int max_pyramid_level_factor = 1 << (settings->default_pyramid_levels - 1); - float search_ratio = 2.3f * max_pyramid_level_factor; - - settings->default_search_size = settings->default_pattern_size*search_ratio; - } -} - static void rna_tracking_defaultSettings_patternUpdate(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { MovieClip *clip = (MovieClip*)ptr->id.data; @@ -223,23 +209,6 @@ static void rna_tracking_trackerSearch_update(Main *UNUSED(bmain), Scene *UNUSED BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); } -static void rna_tracking_trackerAlgorithm_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; - - if (track->tracker == TRACKER_KLT) - BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS); - else - BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); -} - -static void rna_tracking_trackerPyramid_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; - - BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS); -} - static char *rna_trackingCamera_path(PointerRNA *UNUSED(ptr)) { return BLI_sprintfN("tracking.camera"); @@ -484,11 +453,19 @@ void rna_trackingMarkers_delete_frame(MovieTrackingTrack *track, int framenr) #else -static EnumPropertyItem tracker_items[] = { - {TRACKER_KLT, "KLT", 0, "KLT", - "Kanade–Lucas–Tomasi tracker which works with most of video clips, a bit slower than SAD"}, - {TRACKER_SAD, "SAD", 0, "SAD", "Sum of Absolute Differences tracker which can be used when KLT tracker fails"}, - {TRACKER_HYBRID, "Hybrid", 0, "Hybrid", "A hybrid tracker that uses SAD for rough tracking, KLT for refinement."}, +static EnumPropertyItem tracker_motion_model[] = { + {TRACK_MOTION_MODEL_HOMOGRAPHY, "Perspective", 0, "Perspective", + "Search for markers that are perspectively deformed (homography) between frames."}, + {TRACK_MOTION_MODEL_AFFINE, "Affine", 0, "Affine", + "Search for markers that are affine-deformed (t, r, k, and skew) between frames."}, + {TRACK_MOTION_MODEL_TRANSLATION_ROTATION_SCALE, "LocRotScale", 0, "LocRotScale", + "Search for markers that are translated, rotated, and scaled between frames."}, + {TRACK_MOTION_MODEL_TRANSLATION_SCALE, "LocScale", 0, "LocScale", + "Search for markers that are translated and scaled between frames."}, + {TRACK_MOTION_MODEL_TRANSLATION_ROTATION, "LocRot", 0, "LocRot", + "Search for markers that are translated and rotated between frames."}, + {TRACK_MOTION_MODEL_TRANSLATION, "Loc", 0, "Loc", + "Search for markers that are translated between frames."}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem pattern_match_items[] = { @@ -635,33 +612,29 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_range(prop, 0, 300); RNA_def_property_ui_text(prop, "Margin", "Default distance from image boudary at which marker stops tracking"); - /* tracking algorithm */ - prop = RNA_def_property(srna, "default_tracker", PROP_ENUM, PROP_NONE); + /* tracking motion model */ + prop = RNA_def_property(srna, "default_motion_model", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_enum_items(prop, tracker_items); - RNA_def_property_update(prop, 0, "rna_tracking_defaultSettings_levelsUpdate"); - RNA_def_property_ui_text(prop, "Tracker", "Default tracking algorithm to use"); + RNA_def_property_enum_items(prop, tracker_motion_model); + RNA_def_property_ui_text(prop, "Motion model", "Default motion model to use for tracking"); - /* pyramid level for pyramid klt tracking */ - prop = RNA_def_property(srna, "default_pyramid_levels", PROP_INT, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_int_sdna(prop, NULL, "default_pyramid_levels"); - RNA_def_property_range(prop, 1, 16); - RNA_def_property_update(prop, 0, "rna_tracking_defaultSettings_levelsUpdate"); - RNA_def_property_ui_text(prop, "Pyramid levels", "Default number of pyramid levels (increase on blurry footage)"); + /* use_brute */ + prop = RNA_def_property(srna, "default_use_brute", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); + RNA_def_property_ui_text(prop, "Translation-only initialization", "Use a brute-force translation-only initialization when tracking"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); - /* minmal correlation - only used for SAD tracker */ + /* minmal correlation */ prop = RNA_def_property(srna, "default_correlation_min", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_float_sdna(prop, NULL, "default_minimum_correlation"); - RNA_def_property_range(prop, -1.0f, 1.0f); - RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.05, 3); RNA_def_property_ui_text(prop, "Correlation", - "Default minimal value of correlation between matched pattern and reference " - "which is still treated as successful tracking"); + "Default minimum value of correlation between matched pattern and reference " + "that is still treated as successful tracking"); /* default pattern size */ prop = RNA_def_property(srna, "default_pattern_size", PROP_INT, PROP_NONE); @@ -886,25 +859,7 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_struct_name_property(srna, prop); /* Pattern */ - prop = RNA_def_property(srna, "pattern_min", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_array(prop, 2); - RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - RNA_def_property_float_sdna(prop, NULL, "pat_min"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Pattern Min", - "Left-bottom corner of pattern area in normalized coordinates relative " - "to marker position"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerPattern_update"); - - prop = RNA_def_property(srna, "pattern_max", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_array(prop, 2); - RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - RNA_def_property_float_sdna(prop, NULL, "pat_max"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Pattern Max", - "Right-bottom corner of pattern area in normalized coordinates relative " - "to marker position"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerPattern_update"); + /* XXX The four pattern corners are not exported to rna yet */ /* Search */ prop = RNA_def_property(srna, "search_min", PROP_FLOAT, PROP_TRANSLATION); @@ -952,32 +907,29 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_property_range(prop, 0, 300); RNA_def_property_ui_text(prop, "Margin", "Distance from image boudary at which marker stops tracking"); - /* tracking algorithm */ - prop = RNA_def_property(srna, "tracker", PROP_ENUM, PROP_NONE); + /* tracking motion model */ + prop = RNA_def_property(srna, "motion_model", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_enum_items(prop, tracker_items); + RNA_def_property_enum_items(prop, tracker_motion_model); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Tracker", "Tracking algorithm to use"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerAlgorithm_update"); + RNA_def_property_ui_text(prop, "Motion model", "Default motion model to use for tracking"); - /* pyramid level for pyramid klt tracking */ - prop = RNA_def_property(srna, "pyramid_levels", PROP_INT, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_int_sdna(prop, NULL, "pyramid_levels"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_range(prop, 1, 16); - RNA_def_property_ui_text(prop, "Pyramid levels", "Number of pyramid levels (increase on blurry footage)"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerPyramid_update"); - - /* minmal correlation - only used for SAD tracker */ + /* minimum correlation */ prop = RNA_def_property(srna, "correlation_min", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_float_sdna(prop, NULL, "minimum_correlation"); - RNA_def_property_range(prop, -1.0f, 1.0f); - RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.05, 3); RNA_def_property_ui_text(prop, "Correlation", "Minimal value of correlation between matched pattern and reference " - "which is still treated as successful tracking"); + "that is still treated as successful tracking"); + + /* use_brute */ + prop = RNA_def_property(srna, "use_brute", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Translation-only initialization", "Use a brute-force translation only pre-track before refinement"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); /* markers */ prop = RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE); From db46f9b5526bab22a9668f0c9e86e7dd9ea4f116 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 May 2012 18:55:34 +0000 Subject: [PATCH 055/183] fix a bug and storing a bool as a float --- source/blender/editors/transform/transform.c | 2 +- source/blender/editors/transform/transform_conversions.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 0b23bbc1b55..296da01a73e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -237,7 +237,7 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) copy_v2_v2(v, vec); - if (t->options & CTX_MASK) { + if (t->options & CTX_MOVIECLIP) { float aspx, aspy; ED_space_clip_aspect(t->sa->spacedata.first, &aspx, &aspy); v[0] /= aspx; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index ee649888259..fa6dedc5990 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5824,7 +5824,7 @@ void flushTransTracking(TransInfo *t) /* * masking * */ typedef struct TransDataMasking{ - float is_handle; + int is_handle; float handle[2], orig_handle[2]; float vec[3][3]; From d78b7fc946de639bf1c29796b9ce6959ee4aad8f Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Thu, 17 May 2012 20:21:26 +0000 Subject: [PATCH 056/183] Fix the brute-force toggle in the motion tracker. --- source/blender/makesdna/DNA_tracking_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index f15bf4ba8d8..2be7722df8c 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -286,7 +286,7 @@ enum { #define TRACK_MOTION_MODEL_HOMOGRAPHY 5 /* MovieTrackingTrack->algorithm_flag */ -#define TRACK_ALGORITHM_FLAG_USE_BRUTE 0 +#define TRACK_ALGORITHM_FLAG_USE_BRUTE 1 /* MovieTrackingTrack->adjframes */ #define TRACK_MATCH_KEYFRAME 0 From d0ec55b8c28f9abe436fed339c59c1bb2104c494 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Thu, 17 May 2012 21:26:06 +0000 Subject: [PATCH 057/183] For the planar tracker, initialize the warp from the four correspondences after brute force translation search. --- extern/libmv/libmv-capi.cpp | 3 +- extern/libmv/libmv/tracking/track_region.cc | 34 ++++++++++++--------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 482a4c98245..1781eaa747c 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -400,8 +400,7 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options, if (track_region_result.termination == libmv::TrackRegionResult::PARAMETER_TOLERANCE || track_region_result.termination == libmv::TrackRegionResult::FUNCTION_TOLERANCE || track_region_result.termination == libmv::TrackRegionResult::GRADIENT_TOLERANCE || - track_region_result.termination == libmv::TrackRegionResult::NO_CONVERGENCE || - track_region_result.termination == libmv::TrackRegionResult::INSUFFICIENT_CORRELATION) + track_region_result.termination == libmv::TrackRegionResult::NO_CONVERGENCE) { tracking_result = true; } diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index 22c86a7f5b9..22b417c22f6 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -398,7 +398,7 @@ class Quad { struct TranslationWarp { TranslationWarp(const double *x1, const double *y1, const double *x2, const double *y2) { - Vec2 t = Quad(x2, y2).Centroid() - Quad(x1, y1).Centroid() ; + Vec2 t = Quad(x2, y2).Centroid() - Quad(x1, y1).Centroid(); parameters[0] = t[0]; parameters[1] = t[1]; } @@ -908,19 +908,6 @@ void TemplatedTrackRegion(const FloatImage &image1, } // TODO(keir): Check quads to ensure there is some area. - // Prepare the initial warp parameters from the four correspondences. - Warp warp(x1, y1, x2, y2); - - // Decide how many samples to use in the x and y dimensions. - int num_samples_x; - int num_samples_y; - PickSampling(x1, y1, x2, y2, &num_samples_x, &num_samples_y); - - // Compute the warp from rectangular coordinates. - Mat3 canonical_homography = ComputeCanonicalHomography(x1, y1, - num_samples_x, - num_samples_y); - // Prepare the image and gradient. Array3Df image_and_gradient1; Array3Df image_and_gradient2; @@ -938,8 +925,22 @@ void TemplatedTrackRegion(const FloatImage &image1, image2, options.num_extra_points, x1, y1, x2, y2); + for (int i = 0; i < 4; ++i) { + LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); brute (" + << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", " + << (y2[i] - y1[i]) << ")."; + } } + // Prepare the initial warp parameters from the four correspondences. + // Note: This must happen after the brute initialization runs. + Warp warp(x1, y1, x2, y2); + + // Decide how many samples to use in the x and y dimensions. + int num_samples_x; + int num_samples_y; + PickSampling(x1, y1, x2, y2, &num_samples_x, &num_samples_y); + ceres::Solver::Options solver_options; solver_options.linear_solver_type = ceres::DENSE_QR; solver_options.max_num_iterations = options.max_iterations; @@ -957,6 +958,11 @@ void TemplatedTrackRegion(const FloatImage &image1, BoundaryCheckingCallback callback(image2, warp, x1, y1); solver_options.callbacks.push_back(&callback); + // Compute the warp from rectangular coordinates. + Mat3 canonical_homography = ComputeCanonicalHomography(x1, y1, + num_samples_x, + num_samples_y); + // Construct the warp cost function. AutoDiffCostFunction takes ownership. WarpCostFunctor *warp_cost_function = new WarpCostFunctor(options, From d38f2bc99fa274fbc957b504bbaf7fa9ec07d39e Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Thu, 17 May 2012 23:53:32 +0000 Subject: [PATCH 058/183] Implement support for affine tracking in the planar tracker; cleanups. --- extern/libmv/libmv/tracking/track_region.cc | 97 ++++++++++++++------- 1 file changed, 64 insertions(+), 33 deletions(-) diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index 22b417c22f6..58a2077acce 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -410,13 +410,6 @@ struct TranslationWarp { *y2 = y1 + warp_parameters[1]; } - template - void Backward(const T *warp_parameters, - const T &x2, const T& y2, T *x1, T* y1) const { - *x1 = x2 - warp_parameters[0]; - *y1 = y2 - warp_parameters[1]; - } - // Translation x, translation y. enum { NUM_PARAMETERS = 2 }; double parameters[NUM_PARAMETERS]; @@ -461,12 +454,6 @@ struct TranslationScaleWarp { *y2 = y1_scaled + warp_parameters[1]; } - template - void Backward(const T *warp_parameters, - const T &x2, const T& y2, T *x1, T* y1) const { - // XXX - } - // Translation x, translation y, scale. enum { NUM_PARAMETERS = 3 }; double parameters[NUM_PARAMETERS]; @@ -539,12 +526,6 @@ struct TranslationRotationWarp { *y2 = y1_rotated + warp_parameters[1]; } - template - void Backward(const T *warp_parameters, - const T &x2, const T& y2, T *x1, T* y1) const { - // XXX - } - // Translation x, translation y, rotation about the center of Q1 degrees. enum { NUM_PARAMETERS = 3 }; double parameters[NUM_PARAMETERS]; @@ -617,12 +598,6 @@ struct TranslationRotationScaleWarp { *y2 = y1_rotated_scaled + warp_parameters[1]; } - template - void Backward(const T *warp_parameters, - const T &x2, const T& y2, T *x1, T* y1) const { - // XXX - } - // Translation x, translation y, rotation about the center of Q1 degrees, // scale. enum { NUM_PARAMETERS = 4 }; @@ -631,7 +606,69 @@ struct TranslationRotationScaleWarp { Quad q1; }; -// TODO(keir): Finish affine warp. +struct AffineWarp { + AffineWarp(const double *x1, const double *y1, + const double *x2, const double *y2) + : q1(x1, y1) { + Quad q2(x2, y2); + + // The difference in centroids is the best guess for translation. + Vec2 t = q2.Centroid() - q1.Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + + // Estimate the four affine parameters with the usual least squares. + Mat Q1(8, 4); + Vec Q2(8); + for (int i = 0; i < 4; ++i) { + Vec2 v1 = q1.CornerRelativeToCentroid(i); + Vec2 v2 = q2.CornerRelativeToCentroid(i); + + Q1.row(2 * i + 0) << v1[0], v1[1], 0, 0 ; + Q1.row(2 * i + 1) << 0, 0, v1[0], v1[1]; + + Q2(2 * i + 0) = v2[0]; + Q2(2 * i + 1) = v2[1]; + } + + // TODO(keir): Check solution quality. + Vec4 a = Q1.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(Q2); + parameters[2] = a[0]; + parameters[3] = a[1]; + parameters[4] = a[2]; + parameters[5] = a[3]; + + std::cout << "a:" << a.transpose() << "\n"; + std::cout << "t:" << t.transpose() << "\n"; + } + + // See comments in other parameterizations about why the centroid is used. + template + void Forward(const T *p, const T &x1, const T& y1, T *x2, T* y2) const { + // Make the centroid of Q1 the origin. + const T x1_origin = x1 - q1.Centroid()(0); + const T y1_origin = y1 - q1.Centroid()(1); + + // Apply the affine transformation. + const T x1_origin_affine = p[2] * x1_origin + p[3] * y1_origin; + const T y1_origin_affine = p[4] * x1_origin + p[5] * y1_origin; + + // Translate back into the space of Q1 (but affine transformed). + const T x1_affine = x1_origin_affine + q1.Centroid()(0); + const T y1_affine = y1_origin_affine + q1.Centroid()(1); + + // Translate into the space of Q2. + *x2 = x1_affine + p[0]; + *y2 = y1_affine + p[1]; + } + + // Translation x, translation y, rotation about the center of Q1 degrees, + // scale. + enum { NUM_PARAMETERS = 6 }; + double parameters[NUM_PARAMETERS]; + + Quad q1; +}; struct HomographyWarp { HomographyWarp(const double *x1, const double *y1, @@ -674,12 +711,6 @@ struct HomographyWarp { *y2 = yy2 / zz2; } - template - void Backward(const T *warp_parameters, - const T &x2, const T& y2, T *x1, T* y1) const { - // XXX - } - enum { NUM_PARAMETERS = 8 }; double parameters[NUM_PARAMETERS]; }; @@ -1059,7 +1090,7 @@ void TrackRegion(const FloatImage &image1, HANDLE_MODE(TRANSLATION_SCALE, TranslationScaleWarp); HANDLE_MODE(TRANSLATION_ROTATION, TranslationRotationWarp); HANDLE_MODE(TRANSLATION_ROTATION_SCALE, TranslationRotationScaleWarp); - //HANDLE_MODE(AFFINE, AffineWarp); + HANDLE_MODE(AFFINE, AffineWarp); HANDLE_MODE(HOMOGRAPHY, HomographyWarp); #undef HANDLE_MODE } From 7414ccfeeb745ef0e86ee010137865b5398d10a0 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Fri, 18 May 2012 02:12:47 +0000 Subject: [PATCH 059/183] Add light-normalized tracking to the planar tracker This commit adds the ability to normalize patterns by their average value while tracking, to make them invariant to global illumination changes. To see this in action, check out the "Lobby" scene from Hollywood VFX. If you track the markers that are shadowed by the actress, previously they would not track. With the scale adaption on, the tracker would shrink the area to compensate for the changed illumination, losing the track. With "Normalize" turned on, the patch is correctly tracked and scale is maintained. A remaining problem is that only the Ceres cost function is updated to handle the normalization. The brute translation search does not take this into account. Perhaps "Prepass" (see below) should get disabled if normalization is enabled until I fix the prepass to normalize as well. There are a few other changes: - Cleanups in tracking RNA comments. - Bail out of the sampling loop early if the mask is zero; this saves expensive samples of the image derivatives. - Rename the wordy "Translation initialization" to "Prepass" at Sebastian's suggestion. - Fix a bug where the mask was ignored when sampling in the cost functor. --- extern/libmv/libmv-capi.cpp | 1 + extern/libmv/libmv-capi.h | 1 + extern/libmv/libmv/tracking/track_region.cc | 102 +++++++++++++++++- extern/libmv/libmv/tracking/track_region.h | 10 ++ release/scripts/startup/bl_ui/space_clip.py | 2 + source/blender/blenkernel/intern/tracking.c | 1 + source/blender/makesdna/DNA_tracking_types.h | 1 + source/blender/makesrna/intern/rna_tracking.c | 33 ++++-- 8 files changed, 139 insertions(+), 12 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 1781eaa747c..eba4698f198 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -381,6 +381,7 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options, track_region_options.num_extra_points = 1; track_region_options.image1_mask = NULL; track_region_options.use_brute_initialization = options->use_brute; + track_region_options.use_normalized_intensities = options->use_normalization; /* Convert from raw float buffers to libmv's FloatImage. */ libmv::FloatImage old_patch, new_patch; diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index 9fedb9b9683..bbd8f0c30d0 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -55,6 +55,7 @@ struct libmv_trackRegionOptions { int motion_model; int num_iterations; int use_brute; + int use_normalization; double minimum_correlation; double sigma; }; diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index 58a2077acce..ababd0cee90 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -44,6 +44,7 @@ TrackRegionOptions::TrackRegionOptions() max_iterations(20), use_esm(true), use_brute_initialization(true), + use_normalized_intensities(false), sigma(0.9), num_extra_points(0), image1_mask(NULL) { @@ -191,6 +192,14 @@ class WarpCostFunctor { VLOG(2) << "warp_parameters[" << i << "]: " << warp_parameters[i]; } + T src_mean = T(1.0); + T dst_mean = T(1.0); + if (options_.use_normalized_intensities) { + ComputeNormalizingCoefficients(warp_parameters, + &src_mean, + &dst_mean); + } + int cursor = 0; for (int r = 0; r < num_samples_y_; ++r) { for (int c = 0; c < num_samples_x_; ++c) { @@ -198,6 +207,19 @@ class WarpCostFunctor { Vec3 image1_position = canonical_to_image1_ * Vec3(c, r, 1); image1_position /= image1_position(2); + // Sample the mask early; if it's zero, this pixel has no effect. This + // allows early bailout from the expensive sampling that happens below. + double mask_value = 1.0; + if (options_.image1_mask != NULL) { + mask_value = AutoDiff::Sample(*options_.image1_mask, + image1_position[0], + image1_position[1]); + if (mask_value == 0.0) { + residuals[cursor++] = T(0.0); + continue; + } + } + // Compute the location of the destination pixel. T image2_position[2]; warp_.Forward(warp_parameters, @@ -206,7 +228,6 @@ class WarpCostFunctor { &image2_position[0], &image2_position[1]); - // Sample the destination, propagating derivatives. T dst_sample = AutoDiff::Sample(image_and_gradient2_, image2_position[0], @@ -239,6 +260,15 @@ class WarpCostFunctor { image1_position[1])); } + // Normalize the samples by the mean values of each signal. The typical + // light model assumes multiplicative intensity changes with changing + // light, so this is a reasonable choice. Note that dst_mean has + // derivative information attached thanks to autodiff. + if (options_.use_normalized_intensities) { + src_sample /= src_mean; + dst_sample /= dst_mean; + } + // The difference is the error. T error = src_sample - dst_sample; @@ -248,12 +278,80 @@ class WarpCostFunctor { image1_position[0], image1_position[1])); } - residuals[cursor++] = src_sample - dst_sample; + residuals[cursor++] = error; } } return true; } + // For normalized matching, the average and + template + void ComputeNormalizingCoefficients(const T *warp_parameters, + T *src_mean, + T *dst_mean) const { + + *src_mean = T(0.0); + *dst_mean = T(0.0); + double num_samples = 0.0; + for (int r = 0; r < num_samples_y_; ++r) { + for (int c = 0; c < num_samples_x_; ++c) { + // Compute the location of the source pixel (via homography). + Vec3 image1_position = canonical_to_image1_ * Vec3(c, r, 1); + image1_position /= image1_position(2); + + // Sample the mask early; if it's zero, this pixel has no effect. This + // allows early bailout from the expensive sampling that happens below. + double mask_value = 1.0; + if (options_.image1_mask != NULL) { + mask_value = AutoDiff::Sample(*options_.image1_mask, + image1_position[0], + image1_position[1]); + if (mask_value == 0.0) { + continue; + } + } + + // Compute the location of the destination pixel. + T image2_position[2]; + warp_.Forward(warp_parameters, + T(image1_position[0]), + T(image1_position[1]), + &image2_position[0], + &image2_position[1]); + + + // Sample the destination, propagating derivatives. + // TODO(keir): This accumulation can, surprisingly, be done as a + // pre-pass by using integral images. This is complicated by the need + // to store the jets in the integral image, but it is possible. + T dst_sample = AutoDiff::Sample(image_and_gradient2_, + image2_position[0], + image2_position[1]); + + // Sample the source. + // TODO(keir): There is no reason to do this inside the loop; + // precompute this and reuse it. + T src_sample = T(AutoDiff::Sample(image_and_gradient1_, + image1_position[0], + image1_position[1])); + + // Weight the sample by the mask, if one is present. + if (options_.image1_mask != NULL) { + src_sample *= T(mask_value); + dst_sample *= T(mask_value); + } + + *src_mean += src_sample; + *dst_mean += dst_sample; + num_samples += mask_value; + } + } + *src_mean /= T(num_samples); + *dst_mean /= T(num_samples); + std::cout << "Normalization for src:\n" << *src_mean << "\n"; + std::cout << "Normalization for dst:\n" << *dst_mean << "\n"; + } + // TODO(keir): Consider also computing the cost here. double PearsonProductMomentCorrelationCoefficient( const double *warp_parameters) const { diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h index 1a1346f544f..4a1427a6b9f 100644 --- a/extern/libmv/libmv/tracking/track_region.h +++ b/extern/libmv/libmv/tracking/track_region.h @@ -57,6 +57,16 @@ struct TrackRegionOptions { // that the nearby minima is correct, or the search area is too small. bool use_brute_initialization; + // If true, normalize the image patches by their mean before doing the sum of + // squared error calculation. This is reasonable since the effect of + // increasing light intensity is multiplicative on the pixel intensities. + // + // Note: This does nearly double the solving time, so it is not advised to + // turn this on all the time. + bool use_normalized_intensities; + + // The size in pixels of the blur kernel used to both smooth the image and + // take the image derivative. double sigma; // Extra points that should get transformed by the warp. This is useful diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index c17266cf303..ac5b4fe52f4 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -189,6 +189,7 @@ class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel): col.label(text="Tracker:") col.prop(settings, "default_motion_model") col.prop(settings, "default_use_brute") + col.prop(settings, "default_use_normalization") col.prop(settings, "default_correlation_min") col.separator() @@ -488,6 +489,7 @@ class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel): if active: col.prop(active, "motion_model") col.prop(active, "use_brute") + col.prop(active, "use_normalization") col.prop(active, "correlation_min") col.separator() diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 1956492fce9..2456411c2c2 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1735,6 +1735,7 @@ int BKE_tracking_next(MovieTrackingContext *context) /* Configure the tracker */ options.motion_model = track->motion_model; options.use_brute = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) == 0); + options.use_normalization = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) == 0); options.num_iterations = 50; options.minimum_correlation = track->minimum_correlation; options.sigma = 0.9; diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 2be7722df8c..a720a14fdcb 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -287,6 +287,7 @@ enum { /* MovieTrackingTrack->algorithm_flag */ #define TRACK_ALGORITHM_FLAG_USE_BRUTE 1 +#define TRACK_ALGORITHM_FLAG_USE_NORMALIZATION 2 /* MovieTrackingTrack->adjframes */ #define TRACK_MATCH_KEYFRAME 0 diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 34dd471e9c1..565655ccf37 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -590,14 +590,14 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "motion_flag", TRACKING_MOTION_TRIPOD); RNA_def_property_ui_text(prop, "Tripod Motion", "Use special solver to track a stable camera position, such as a tripod"); - /* limit frames */ + /* default_limit_frames */ prop = RNA_def_property(srna, "default_frames_limit", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "default_frames_limit"); RNA_def_property_range(prop, 0, SHRT_MAX); RNA_def_property_ui_text(prop, "Frames Limit", "Every tracking cycle, this number of frames are tracked"); - /* pattern match */ + /* default_pattern_match */ prop = RNA_def_property(srna, "default_pattern_match", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_enum_sdna(prop, NULL, "default_pattern_match"); @@ -605,14 +605,14 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pattern Match", "Track pattern from given frame when tracking marker to next frame"); - /* margin */ + /* default_margin */ prop = RNA_def_property(srna, "default_margin", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "default_margin"); RNA_def_property_range(prop, 0, 300); RNA_def_property_ui_text(prop, "Margin", "Default distance from image boudary at which marker stops tracking"); - /* tracking motion model */ + /* default_tracking_motion_model */ prop = RNA_def_property(srna, "default_motion_model", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -622,10 +622,16 @@ static void rna_def_trackingSettings(BlenderRNA *brna) /* use_brute */ prop = RNA_def_property(srna, "default_use_brute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); - RNA_def_property_ui_text(prop, "Translation-only initialization", "Use a brute-force translation-only initialization when tracking"); + RNA_def_property_ui_text(prop, "Prepass", "Use a brute-force translation-only initialization when tracking"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); - /* minmal correlation */ + /* default use_normalization */ + prop = RNA_def_property(srna, "default_use_normalization", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_NORMALIZATION); + RNA_def_property_ui_text(prop, "Normalize", "Normalize light intensities while tracking. Slower."); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); + + /* default minmal correlation */ prop = RNA_def_property(srna, "default_correlation_min", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -652,19 +658,19 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_tracking_defaultSettings_searchUpdate"); RNA_def_property_ui_text(prop, "Search Size", "Size of search area for newly created tracks"); - /* use_red_channel */ + /* default use_red_channel */ prop = RNA_def_property(srna, "use_default_red_channel", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "default_flag", TRACK_DISABLE_RED); RNA_def_property_ui_text(prop, "Use Red Channel", "Use red channel from footage for tracking"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); - /* use_green_channel */ + /* default_use_green_channel */ prop = RNA_def_property(srna, "use_default_green_channel", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "default_flag", TRACK_DISABLE_GREEN); RNA_def_property_ui_text(prop, "Use Green Channel", "Use green channel from footage for tracking"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); - /* use_blue_channel */ + /* default_use_blue_channel */ prop = RNA_def_property(srna, "use_default_blue_channel", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "default_flag", TRACK_DISABLE_BLUE); RNA_def_property_ui_text(prop, "Use Blue Channel", "Use blue channel from footage for tracking"); @@ -928,7 +934,14 @@ static void rna_def_trackingTrack(BlenderRNA *brna) prop = RNA_def_property(srna, "use_brute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Translation-only initialization", "Use a brute-force translation only pre-track before refinement"); + RNA_def_property_ui_text(prop, "Prepass", "Use a brute-force translation only pre-track before refinement"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); + + /* use_brute */ + prop = RNA_def_property(srna, "use_normalization", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_NORMALIZATION); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Normalize", "Normalize light intensities while tracking. Slower."); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); /* markers */ From f21cd531d6233ec95e1f3515ba1d77977154d5c9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 18 May 2012 08:59:05 +0000 Subject: [PATCH 060/183] mask editor now stores points/handles in 1:1 aspect, makes tool code _much_ more logical/easier. --- source/blender/blenkernel/BKE_mask.h | 5 ++ source/blender/blenkernel/intern/mask.c | 50 ++++++++++++++++++- source/blender/editors/mask/mask_editor.c | 1 + .../editors/space_clip/clip_dopesheet_ops.c | 2 + .../blender/editors/space_clip/clip_editor.c | 5 +- .../blender/editors/space_clip/space_clip.c | 22 +++++++- source/blender/editors/transform/transform.c | 48 +++++++++++++----- .../editors/transform/transform_conversions.c | 5 +- .../composite/nodes/node_composite_mask.c | 20 ++++++++ 9 files changed, 136 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 26beed4645c..1c64e00630c 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -34,6 +34,8 @@ struct MaskShape; struct MaskSpline; struct MaskSplinePoint; struct MaskSplinePointUW; +struct MovieClip; +struct MovieClipUser; struct Scene; /* shapes */ @@ -77,6 +79,9 @@ struct Mask *BKE_mask_new(const char *name); void BKE_mask_free(struct Mask *mask); void BKE_mask_unlink(struct Main *bmain, struct Mask *mask); +void BKE_mask_coord_from_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]); +void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]); + /* parenting */ void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 0af0c1c7aa5..ae8a6fa737c 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -52,6 +52,7 @@ #include "BKE_main.h" #include "BKE_mask.h" #include "BKE_tracking.h" +#include "BKE_movieclip.h" #include "BKE_utildefines.h" /* shapes */ @@ -727,6 +728,49 @@ void BKE_mask_unlink(Main *bmain, Mask *mask) mask->id.us = 0; } +void BKE_mask_coord_from_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2]) +{ + int width, height; + + /* scaling for the clip */ + BKE_movieclip_get_size(clip, user, &width, &height); + + if (width == height) { + r_co[0] = co[0]; + r_co[1] = co[1]; + } + else if (width < height) { + r_co[0] = ((co[0] - 0.5f) * ((float)width / (float)height)) + 0.5f; + r_co[1] = co[1]; + } + else { /* (width > height) */ + r_co[0] = co[0]; + r_co[1] = ((co[1] - 0.5f) * ((float)height / (float)width)) + 0.5f; + } +} + +/* as above but divide */ +void BKE_mask_coord_to_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2]) +{ + int width, height; + + /* scaling for the clip */ + BKE_movieclip_get_size(clip, user, &width, &height); + + if (width == height) { + r_co[0] = co[0]; + r_co[1] = co[1]; + } + else if (width < height) { + r_co[0] = ((co[0] - 0.5f) / ((float)width / (float)height)) + 0.5f; + r_co[1] = co[1]; + } + else { /* (width > height) */ + r_co[0] = co[0]; + r_co[1] = ((co[1] - 0.5f) / ((float)height / (float)width)) + 0.5f; + } +} + static void evaluate_mask_parent(MaskParent *parent, float ctime, float co[2]) { if (!parent) @@ -744,10 +788,12 @@ static void evaluate_mask_parent(MaskParent *parent, float ctime, float co[2]) if (ob) { MovieTrackingTrack *track = BKE_tracking_named_track(tracking, ob, parent->sub_parent); + MovieClipUser user = {0}; + user.framenr = ctime; + if (track) { MovieTrackingMarker *marker = BKE_tracking_get_marker(track, ctime); - - copy_v2_v2(co, marker->pos); + BKE_mask_coord_from_movieclip(clip, &user, co, marker->pos); } } } diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index 633f75c643b..a868696941c 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -81,6 +81,7 @@ void ED_mask_mouse_pos(bContext *C, wmEvent *event, float co[2]) if (sc) { ED_clip_mouse_pos(C, event, co); + BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co); } else { /* possible other spaces from which mask editing is available */ diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c index 78e346cba47..4a390241629 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_ops.c +++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c @@ -59,6 +59,7 @@ #include "clip_intern.h" // own include +#if 0 static int ED_space_clip_dopesheet_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); @@ -73,6 +74,7 @@ static int ED_space_clip_dopesheet_poll(bContext *C) return FALSE; } +#endif /********************** select channel operator *********************/ diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 1126e96b194..afcd18dfbe8 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -268,10 +268,13 @@ void ED_space_clip_mask_aspect(SpaceClip *sc, float *aspx, float *aspy) int w, h; ED_space_clip_aspect(sc, aspx, aspy); - ED_space_clip_size(sc, &w, &h); + ED_space_clip_size(sc, &w, &h); + /* now this is not accounted for! */ +#if 0 *aspx *= (float)w; *aspy *= (float)h; +#endif if(*aspx < *aspy) { *aspy= *aspy / *aspx; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index c1bbc75c87a..b4810a22608 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1101,6 +1101,10 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) int width, height; float zoomx, zoomy, aspx, aspy; + /* frame image */ + float maxdim; + float xofs, yofs; + /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); @@ -1108,10 +1112,24 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) ED_space_clip_zoom(sc, ar, &zoomx, &zoomy); ED_space_clip_aspect(sc, &aspx, &aspy); + /* frame the image */ + maxdim = maxf(width, height); + if (width == height) { + xofs = yofs = 0; + } + else if (width < height) { + xofs = ((height - width) / -2.0f) * zoomx; + yofs = 0.0f; + } + else { /* (width > height) */ + xofs = 0.0f; + yofs = ((width - height) / -2.0f) * zoomy; + } + /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */ glPushMatrix(); - glTranslatef(x, y, 0); - glScalef(width*zoomx, height*zoomy, 0); + glTranslatef(x + xofs, y + yofs, 0); + glScalef(maxdim * zoomx, maxdim * zoomy, 0); glMultMatrixf(sc->stabmat); ED_mask_draw((bContext *)C, width*aspx, height*aspy, zoomx, zoomy); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 296da01a73e..d3626851173 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -163,12 +163,22 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) else if (t->spacetype==SPACE_CLIP) { View2D *v2d = t->view; float divx, divy; + float mulx, muly; divx = v2d->mask.xmax-v2d->mask.xmin; divy = v2d->mask.ymax-v2d->mask.ymin; - r_vec[0] = (v2d->cur.xmax-v2d->cur.xmin)*(dx)/divx; - r_vec[1] = (v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy; + mulx = (v2d->cur.xmax-v2d->cur.xmin); + muly = (v2d->cur.ymax-v2d->cur.ymin); + + if (t->options & CTX_MASK) { + /* clamp w/h, mask only */ + divx = divy = minf(divx, divy); + mulx = muly = minf(mulx, muly); + } + + r_vec[0] = mulx * (dx) / divx; + r_vec[1] = muly * (dy) / divy; r_vec[2] = 0.0f; if (t->options & CTX_MASK) { @@ -303,17 +313,22 @@ void applyAspectRatio(TransInfo *t, float vec[2]) if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { SpaceClip *sc = t->sa->spacedata.first; float aspx, aspy; - int width, height; - ED_space_clip_size(sc, &width, &height); - if (t->options & CTX_MOVIECLIP) + if (t->options & CTX_MOVIECLIP) { + int width, height; + ED_space_clip_size(sc, &width, &height); ED_space_clip_aspect(sc, &aspx, &aspy); - else if (t->options & CTX_MASK) + + vec[0] *= width / aspx; + vec[1] *= height / aspy; + } + else if (t->options & CTX_MASK) { ED_space_clip_mask_aspect(sc, &aspx, &aspy); - vec[0] *= width / aspx; - vec[1] *= height / aspy; + vec[0] /= aspx; + vec[1] /= aspy; + } } } } @@ -340,15 +355,22 @@ void removeAspectRatio(TransInfo *t, float vec[2]) if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { SpaceClip *sc = t->sa->spacedata.first; float aspx, aspy; - int width, height; - if (t->options & CTX_MOVIECLIP) + if (t->options & CTX_MOVIECLIP) { + int width, height; ED_space_clip_size(sc, &width, &height); - else if (t->options & CTX_MASK) ED_space_clip_aspect(sc, &aspx, &aspy); - vec[0] *= aspx / width; - vec[1] *= aspy / height; + vec[0] *= aspx / width; + vec[1] *= aspy / height; + } + else if (t->options & CTX_MASK) { + ED_space_clip_aspect(sc, &aspx, &aspy); + ED_space_clip_mask_aspect(sc, &aspx, &aspy); + + vec[0] *= aspx; + vec[1] *= aspy; + } } } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index fa6dedc5990..1ea32b78a9e 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5875,12 +5875,9 @@ static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, TransDat } } else { - int width, height; - tdm->is_handle = TRUE; - ED_space_clip_mask_size(sc, &width, &height); - BKE_mask_point_handle(point, width, height, tdm->handle); + BKE_mask_point_handle(point, aspx, aspy, tdm->handle); copy_v2_v2(tdm->orig_handle, tdm->handle); diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c index 1dbe057a869..a586824e6e1 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mask.c +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -94,6 +94,26 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); + /* TODO, make this optional! */ + if (sx != sy) { + float *fp; + int i; + float asp; + + if (sx < sy) { + fp = &diff_points[0]; + asp = (float)sx / (float)sy; + } + else { + fp = &diff_points[1]; + asp = (float)sy / (float)sx; + } + + for (i = 0; i < tot_diff_point; i++, fp += 2) { + (*fp) = (((*fp) - 0.5f) / asp) + 0.5f; + } + } + if (tot_diff_point) { PLX_raskterize(diff_points, tot_diff_point, res, sx, sy); From 2da49c4a8f1eea7ac382c0a38e69f2c3de30f4ea Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 18 May 2012 09:33:50 +0000 Subject: [PATCH 061/183] Rotation support for motion tracking markers Implemented general transformation tool Rotation for motion tracking data. Mainly used to rotate pattern of markers. To achieve most of usability, added configurable pivot point which is in fact was median point before, but now can be chosen from boundbox center, median point or individual centers. Individual centers means transformation would be performed around marker's position, which is useful for rotation and scale. Also implemented alternative scaling transformation -- hit S, S leads to scaling of pattern area only. TODO: - clamping in some cases isn't working well, but that's easier to be resolved after moving search are to marker. - Update startup.blend so clip editor in Motion Tracking screen would be set to Individual Centers by default. --- release/scripts/startup/bl_ui/space_clip.py | 3 +- source/blender/blenloader/intern/readfile.c | 19 +++ source/blender/editors/include/ED_clip.h | 1 + .../blender/editors/space_clip/clip_editor.c | 39 +++++- .../blender/editors/space_clip/space_clip.c | 2 + source/blender/editors/transform/transform.c | 55 +++++---- .../editors/transform/transform_conversions.c | 113 +++++++++++------- .../editors/transform/transform_generics.c | 9 ++ source/blender/makesdna/DNA_space_types.h | 2 +- source/blender/makesrna/intern/rna_space.c | 17 +++ 10 files changed, 190 insertions(+), 70 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index ac5b4fe52f4..90b3901c002 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -54,7 +54,8 @@ class CLIP_HT_header(Header): if clip: if sc.view == 'CLIP': layout.prop(sc, "mode", text="") - if sc.view == 'GRAPH': + layout.prop(sc, "pivot_point", text="", icon_only=True) + elif sc.view == 'GRAPH': row = layout.row(align=True) if sc.show_filters: diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index bb944eaf429..2e30f756b43 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7612,6 +7612,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) { MovieClip *clip; + bScreen *sc; for (clip = main->movieclip.first; clip; clip = clip->id.next) { MovieTrackingTrack *track; @@ -7643,6 +7644,24 @@ static void do_versions(FileData *fd, Library *lib, Main *main) track = track->next; } } + + for (sc = main->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; + + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sclip = (SpaceClip *)sl; + + if (sclip->around == 0) { + sclip->around = V3D_CENTROID; + } + } + } + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 846100b0d19..7e1505b652f 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -58,6 +58,7 @@ struct Mask *ED_space_clip_mask(struct SpaceClip *sc); void ED_space_clip_size(struct SpaceClip *sc, int *width, int *height); void ED_space_clip_zoom(struct SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy); void ED_space_clip_aspect(struct SpaceClip *sc, float *aspx, float *aspy); +void ED_space_clip_aspect_dimension_aware(struct SpaceClip *sc, float *aspx, float *aspy); void ED_space_clip_mask_size(struct SpaceClip *sc, int *width, int *height); void ED_space_clip_mask_aspect(struct SpaceClip *sc, float *aspx, float *aspy); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index afcd18dfbe8..f16ef21b707 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -249,9 +249,15 @@ void ED_space_clip_size(SpaceClip *sc, int *width, int *height) void ED_space_clip_mask_size(SpaceClip *sc, int *width, int *height) { - if(!sc->mask) { - *width= 0; - *height= 0; + /* quite the same as ED_space_clip_size, but it also runs aspect correction on output resolution + * this is needed because mask should be rasterized with exactly the same resolution as + * currently displaying frame and it doesn't have access to aspect correction currently + * used for display. (sergey) + */ + + if (!sc->mask) { + *width = 0; + *height = 0; } else { float aspx, aspy; @@ -306,6 +312,33 @@ void ED_space_clip_aspect(SpaceClip *sc, float *aspx, float *aspy) *aspx = *aspy = 1.0f; } +void ED_space_clip_aspect_dimension_aware(SpaceClip *sc, float *aspx, float *aspy) +{ + int w, h; + + /* most of tools does not require aspect to be returned with dimensions correction + * due to they're invariant to this stuff, but some transformation tools like rotation + * should be aware of aspect correction caused by different resolution in different + * directions. + * mainly this is sued for transformation stuff + */ + + ED_space_clip_aspect(sc, aspx, aspy); + ED_space_clip_size(sc, &w, &h); + + *aspx *= (float)w; + *aspy *= (float)h; + + if(*aspx < *aspy) { + *aspy= *aspy / *aspx; + *aspx= 1.0f; + } + else { + *aspx= *aspx / *aspy; + *aspy= 1.0f; + } +} + void ED_clip_update_frame(const Main *mainp, int cfra) { wmWindowManager *wm; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index b4810a22608..6ebcaf4ea16 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -35,6 +35,7 @@ #include "DNA_scene_types.h" #include "DNA_mask_types.h" #include "DNA_movieclip_types.h" +#include "DNA_view3d_types.h" /* for pivot point */ #include "MEM_guardedalloc.h" @@ -239,6 +240,7 @@ static SpaceLink *clip_new(const bContext *C) sc->zoom = 1.0f; sc->path_length = 20; sc->scopes.track_preview_height = 120; + sc->around = V3D_LOCAL; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for clip"); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index d3626851173..06bcf11bfe4 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -244,21 +244,17 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) } else if (t->spacetype==SPACE_CLIP) { float v[2]; + float aspx = 1.0f, aspy = 1.0f; copy_v2_v2(v, vec); - if (t->options & CTX_MOVIECLIP) { - float aspx, aspy; - ED_space_clip_aspect(t->sa->spacedata.first, &aspx, &aspy); - v[0] /= aspx; - v[1] /= aspy; - } - else if (t->options & CTX_MASK) { - float aspx, aspy; + if (t->options & CTX_MOVIECLIP) + ED_space_clip_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy); + else if (t->options & CTX_MASK) ED_space_clip_mask_aspect(t->sa->spacedata.first, &aspx, &aspy); - v[0] /= aspx; - v[1] /= aspy; - } + + v[0] /= aspx; + v[1] /= aspy; UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1); } @@ -316,12 +312,10 @@ void applyAspectRatio(TransInfo *t, float vec[2]) if (t->options & CTX_MOVIECLIP) { - int width, height; - ED_space_clip_size(sc, &width, &height); - ED_space_clip_aspect(sc, &aspx, &aspy); + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); - vec[0] *= width / aspx; - vec[1] *= height / aspy; + vec[0] /= aspx; + vec[1] /= aspy; } else if (t->options & CTX_MASK) { ED_space_clip_mask_aspect(sc, &aspx, &aspy); @@ -357,12 +351,10 @@ void removeAspectRatio(TransInfo *t, float vec[2]) float aspx, aspy; if (t->options & CTX_MOVIECLIP) { - int width, height; - ED_space_clip_size(sc, &width, &height); - ED_space_clip_aspect(sc, &aspx, &aspy); + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); - vec[0] *= aspx / width; - vec[1] *= aspy / height; + vec[0] *= aspx; + vec[1] *= aspy; } else if (t->options & CTX_MASK) { ED_space_clip_aspect(sc, &aspx, &aspy); @@ -711,7 +703,7 @@ int transformEvent(TransInfo *t, wmEvent *event) t->redraw |= TREDRAW_HARD; } else if (t->mode == TFM_TRANSLATION) { - if(t->options & (CTX_MOVIECLIP | CTX_MASK)) { + if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { restoreTransObjects(t); t->flag ^= T_ALT_TRANSFORM; @@ -721,7 +713,7 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case TFM_MODAL_ROTATE: /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & CTX_MOVIECLIP)) { + if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { if ( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { resetTransRestrictions(t); @@ -748,6 +740,14 @@ int transformEvent(TransInfo *t, wmEvent *event) initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; } + else if (t->mode == TFM_RESIZE) { + if (t->options & CTX_MOVIECLIP) { + restoreTransObjects(t); + + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } + } break; case TFM_MODAL_SNAP_INV_ON: @@ -976,7 +976,7 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case RKEY: /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & CTX_MOVIECLIP)) { + if (!(t->options & CTX_TEXTURE)) { if ( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { resetTransRestrictions(t); @@ -2737,6 +2737,9 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { copy_v3_v3(center, td->center); } + else if (t->options & CTX_MOVIECLIP) { + copy_v3_v3(center, td->center); + } else { copy_v3_v3(center, t->center); } @@ -3020,6 +3023,10 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short { center = td->center; } + + if (t->options & CTX_MOVIECLIP) { + center = td->center; + } } if (t->flag & T_POINTS) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 1ea32b78a9e..85d54c0d6e3 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5388,23 +5388,24 @@ typedef struct TransDataTracking { short coord; } TransDataTracking; -static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt, MovieTrackingTrack *track, - int area, float *loc, float *rel, float *off) +static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt, + MovieTrackingTrack *track, MovieTrackingMarker *marker, + int area, float *loc, float *rel, float *off, float aspx, float aspy) { int anchor = area == TRACK_AREA_POINT && off; tdt->mode = transDataTracking_ModeTracks; if (anchor) { - td2d->loc[0] = rel[0]; /* hold original location */ - td2d->loc[1] = rel[1]; + td2d->loc[0] = rel[0] * aspx; /* hold original location */ + td2d->loc[1] = rel[1] * aspy; tdt->loc= loc; td2d->loc2d = loc; /* current location */ } else { - td2d->loc[0] = loc[0]; /* hold original location */ - td2d->loc[1] = loc[1]; + td2d->loc[0] = loc[0] * aspx; /* hold original location */ + td2d->loc[1] = loc[1] * aspy; td2d->loc2d = loc; /* current location */ } @@ -5418,8 +5419,8 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra if (rel) { if (!anchor) { - td2d->loc[0] += rel[0]; - td2d->loc[1] += rel[1]; + td2d->loc[0] += rel[0] * aspx; + td2d->loc[1] += rel[1] * aspy; } copy_v2_v2(tdt->srelative, rel); @@ -5430,9 +5431,12 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra td->flag = 0; td->loc = td2d->loc; - copy_v3_v3(td->center, td->loc); copy_v3_v3(td->iloc, td->loc); + //copy_v3_v3(td->center, td->loc); + td->center[0] = marker->pos[0] * aspx; + td->center[1] = marker->pos[1] * aspy; + memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; @@ -5447,28 +5451,36 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra } static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d, - TransDataTracking *tdt, MovieTrackingTrack *track) + TransDataTracking *tdt, MovieTrackingTrack *track, float aspx, float aspy) { MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, sc->user.framenr); tdt->flag = marker->flag; marker->flag &= ~(MARKER_DISABLED|MARKER_TRACKED); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, track->offset, marker->pos, track->offset); + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, + track->offset, marker->pos, track->offset, aspx, aspy); - if (track->flag & SELECT) - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, marker->pos, NULL, NULL); + if (track->flag & SELECT) { + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, + marker->pos, NULL, NULL, aspx, aspy); + } if (track->pat_flag & SELECT) { - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[0], marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[1], marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[2], marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[3], marker->pos, NULL); + int a; + + for (a = 0; a < 4; a++) { + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_PAT, + marker->pattern_corners[a], marker->pos, NULL, aspx, aspy); + } } if (track->search_flag & SELECT) { - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_SEARCH, track->search_min, marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_SEARCH, track->search_max, marker->pos, NULL); + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH, + track->search_min, marker->pos, NULL, aspx, aspy); + + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH, + track->search_max, marker->pos, NULL, aspx, aspy); } } @@ -5495,6 +5507,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) MovieTrackingMarker *marker; TransDataTracking *tdt; int framenr = sc->user.framenr; + float aspx, aspy; /* count */ t->total = 0; @@ -5522,6 +5535,8 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) if (t->total == 0) return; + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); + td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransTracking TransData"); td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransTracking TransData2D"); tdt = t->customData = MEM_callocN(t->total*sizeof(TransDataTracking), "TransTracking TransDataTracking"); @@ -5534,7 +5549,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { marker = BKE_tracking_get_marker(track, framenr); - trackToTransData(sc, td, td2d, tdt, track); + trackToTransData(sc, td, td2d, tdt, track, aspx, aspy); /* offset */ td++; @@ -5704,9 +5719,6 @@ static void createTransTrackingData(bContext *C, TransInfo *t) if (!clip || width == 0 || height == 0) return; - if (!ELEM(t->mode, TFM_RESIZE, TFM_TRANSLATION)) - return; - if (ar->regiontype == RGN_TYPE_PREVIEW) { /* transformation was called from graph editor */ createTransTrackingCurvesData(C, t); @@ -5774,10 +5786,14 @@ static void cancelTransTracking(TransInfo *t) void flushTransTracking(TransInfo *t) { + SpaceClip *sc = t->sa->spacedata.first; TransData *td; TransData2D *td2d; TransDataTracking *tdt; int a; + float aspx, aspy; + + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); if (t->state == TRANS_CANCEL) cancelTransTracking(t); @@ -5785,31 +5801,46 @@ void flushTransTracking(TransInfo *t) /* flush to 2d vector from internally used 3d vector */ for (a=0, td= t->data, td2d= t->data2d, tdt= t->customData; atotal; a++, td2d++, td++, tdt++) { if (tdt->mode == transDataTracking_ModeTracks) { + float loc2d[2]; + + if (t->mode == TFM_ROTATION && tdt->area == TRACK_AREA_SEARCH) { + continue; + } + + loc2d[0] = td2d->loc[0] / aspx; + loc2d[1] = td2d->loc[1] / aspy; + if (t->flag & T_ALT_TRANSFORM) { - if (tdt->area == TRACK_AREA_POINT && tdt->relative) { - float d[2], d2[2]; + if (t->mode == TFM_RESIZE) { + if (tdt->area != TRACK_AREA_PAT) + continue; + } + else if (t->mode == TFM_TRANSLATION) { + if (tdt->area == TRACK_AREA_POINT && tdt->relative) { + float d[2], d2[2]; - if (!tdt->smarkers) { - tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers)*tdt->markersnr, "flushTransTracking markers"); - for (a = 0; a < tdt->markersnr; a++) - copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos); + if (!tdt->smarkers) { + tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers)*tdt->markersnr, "flushTransTracking markers"); + for (a = 0; a < tdt->markersnr; a++) + copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos); + } + + sub_v2_v2v2(d, loc2d, tdt->soffset); + sub_v2_v2(d, tdt->srelative); + + sub_v2_v2v2(d2, loc2d, tdt->srelative); + + for (a= 0; amarkersnr; a++) + add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2); + + negate_v2_v2(td2d->loc2d, d); } - - sub_v2_v2v2(d, td2d->loc, tdt->soffset); - sub_v2_v2(d, tdt->srelative); - - sub_v2_v2v2(d2, td2d->loc, tdt->srelative); - - for (a= 0; amarkersnr; a++) - add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2); - - negate_v2_v2(td2d->loc2d, d); } } if (tdt->area!=TRACK_AREA_POINT || tdt->relative==0) { - td2d->loc2d[0] = td2d->loc[0]; - td2d->loc2d[1] = td2d->loc[1]; + td2d->loc2d[0] = loc2d[0]; + td2d->loc2d[1] = loc2d[1]; if (tdt->relative) sub_v2_v2(td2d->loc2d, tdt->relative); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index d2f27b87b8c..e3ca0957c25 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -660,6 +660,10 @@ static void recalcData_spaceclip(TransInfo *t) if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); } + else if (t->mode == TFM_ROTATION) { + if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) + BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); + } } track = track->next; @@ -1114,6 +1118,11 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->view = &ar->v2d; t->around = sipo->around; } + else if (t->spacetype==SPACE_CLIP) { + SpaceClip *sclip = sa->spacedata.first; + t->view = &ar->v2d; + t->around = sclip->around; + } else { if (ar) { // XXX for now, get View2D from the active region diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 640961f80f2..da07ffd7f9a 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -532,7 +532,7 @@ typedef struct SpaceClip { short dope_sort; /* sort order in dopesheet view */ short dope_flag; /* dopsheet view flags */ - int pad3; + int around; /* pivot point for transforms */ /* **** mask editing **** */ struct Mask *mask; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index d63110c4646..b2c13f8717a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2989,6 +2989,16 @@ static void rna_def_space_clip(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem pivot_items[] = { + {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", + "Pivot around bounding box center of selected object(s)"}, + {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION, + "Individual Origins", "Pivot around each object's own origin"}, + {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point", + "Pivot around the median point of selected objects"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "SpaceClipEditor", "Space"); RNA_def_struct_sdna(srna, "SpaceClip"); RNA_def_struct_ui_text(srna, "Space Clip Editor", "Clip editor space data"); @@ -3182,6 +3192,13 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Grease Pencil Source", "Where the grease pencil comes from"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + /* pivot point */ + prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "around"); + RNA_def_property_enum_items(prop, pivot_items); + RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL); + /* ** dopesheet ** */ /* dopesheet sort */ From a8a22d968c637a877210fc756e74731d9403f455 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 18 May 2012 09:36:32 +0000 Subject: [PATCH 062/183] mask: remove aspect arguments which are no longer needed. --- source/blender/blenkernel/BKE_mask.h | 11 ++--- source/blender/blenkernel/intern/mask.c | 48 +++++++------------ source/blender/editors/include/ED_mask.h | 2 +- source/blender/editors/mask/mask_draw.c | 43 +++++------------ source/blender/editors/mask/mask_ops.c | 24 +++++----- .../blender/editors/space_clip/space_clip.c | 2 +- .../editors/transform/transform_conversions.c | 2 +- source/blender/makesdna/DNA_mask_types.h | 12 ++--- 8 files changed, 55 insertions(+), 89 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 1c64e00630c..88934e4af84 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -54,21 +54,20 @@ void BKE_mask_shape_unique_name(struct Mask *mask, struct MaskShape *shape); struct MaskSpline *BKE_mask_spline_add(struct MaskShape *shape); int BKE_mask_spline_resolution(struct MaskSpline *spline); float *BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point); -float *BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, float aspx, - float aspy, int *tot_feather_point); -float *BKE_mask_spline_feather_points(struct MaskSpline *spline, float aspx, float aspy, int *tot_feather_point); +float *BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point); +float *BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point); /* point */ int BKE_mask_point_has_handle(struct MaskSplinePoint *point); -void BKE_mask_point_handle(struct MaskSplinePoint *point, float aspx, float aspy, float handle[2]); +void BKE_mask_point_handle(struct MaskSplinePoint *point, float handle[2]); void BKE_mask_point_set_handle(struct MaskSplinePoint *point, float loc[2], int keep_direction, float aspx, float aspy, float orig_handle[2], float orig_vec[3][3]); float *BKE_mask_point_segment_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, int *tot_diff_point); float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, - float aspx, float aspy, int *tot_feather_point); + int *tot_feather_point); void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2]); void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, - float aspx, float aspy, float u, float n[2]); + float u, float n[2]); float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *point, float u); struct MaskSplinePointUW *BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw); void BKE_mask_point_add_uw(struct MaskSplinePoint *point, float u, float w); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index ae8a6fa737c..863945e6baf 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -257,8 +257,7 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) return diff_points; } -float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, float aspx, float aspy, - int *tot_feather_point) +float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point) { float *feather, *fp; int i, j, tot, resol = BKE_mask_spline_feather_resolution(spline); @@ -274,7 +273,7 @@ float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, float a float co[2], n[2]; BKE_mask_point_segment_co(spline, point, u, co); - BKE_mask_point_normal(spline, point, aspx, aspy, u, n); + BKE_mask_point_normal(spline, point, u, n); weight = BKE_mask_point_weight(spline, point, u); fp[0] = co[0] + n[0] * weight; @@ -287,7 +286,7 @@ float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, float a return feather; } -float *BKE_mask_spline_feather_points(MaskSpline *spline, float aspx, float aspy, int *tot_feather_point) +float *BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point) { int i, tot = 0; float *feather, *fp; @@ -308,7 +307,7 @@ float *BKE_mask_spline_feather_points(MaskSpline *spline, float aspx, float aspy float weight, n[2]; int j; - BKE_mask_point_normal(spline, point, aspx, aspy, 0.0f, n); + BKE_mask_point_normal(spline, point, 0.0f, n); weight = BKE_mask_point_weight(spline, point, 0.0f); fp[0] = bezt->vec[1][0] + n[0] * weight; @@ -320,7 +319,7 @@ float *BKE_mask_spline_feather_points(MaskSpline *spline, float aspx, float aspy float co[2]; BKE_mask_point_segment_co(spline, point, u, co); - BKE_mask_point_normal(spline, point, aspx, aspy, u, n); + BKE_mask_point_normal(spline, point, u, n); weight = BKE_mask_point_weight(spline, point, u); fp[0] = co[0] + n[0] * weight; @@ -344,17 +343,14 @@ int BKE_mask_point_has_handle(MaskSplinePoint *point) return bezt->h1 == HD_ALIGN; } -void BKE_mask_point_handle(MaskSplinePoint *point, float aspx, float aspy, float handle[2]) +void BKE_mask_point_handle(MaskSplinePoint *point, float handle[2]) { float vec[2]; sub_v2_v2v2(vec, point->bezt.vec[0], point->bezt.vec[1]); - vec[0] *= aspx; - vec[1] *= aspy; - - handle[0] = (point->bezt.vec[1][0] * aspx + vec[1]) / aspx; - handle[1] = (point->bezt.vec[1][1] * aspy - vec[0]) / aspy; + handle[0] = (point->bezt.vec[1][0] + vec[1]); + handle[1] = (point->bezt.vec[1][1] - vec[0]); } void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_direction, float aspx, float aspy, @@ -406,8 +402,7 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di } } -float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, float aspx, float aspy, - int *tot_feather_point) +float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_feather_point) { float *feather, *fp; int i, resol = BKE_mask_spline_feather_resolution(spline); @@ -419,7 +414,7 @@ float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint * float co[2], n[2]; BKE_mask_point_segment_co(spline, point, u, co); - BKE_mask_point_normal(spline, point, aspx, aspy, u, n); + BKE_mask_point_normal(spline, point, u, n); weight = BKE_mask_point_weight(spline, point, u); fp[0] = co[0] + n[0] * weight; @@ -493,7 +488,7 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float interp_v2_v2v2(co, r0, r1, u); } -void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float aspx, float aspy, float u, float n[2]) +void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, float n[2]) { BezTriple *bezt = &point->bezt, *next; float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2]; @@ -504,21 +499,15 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float asp else next = NULL; } - else next = &((point + 1))->bezt; + else { + next = &((point + 1))->bezt; + } if (!next) { - BKE_mask_point_handle(point, aspx, aspy, vec); + BKE_mask_point_handle(point, vec); sub_v2_v2v2(n, vec, bezt->vec[1]); - - n[0] *= aspx; - n[1] *= aspy; - normalize_v2(n); - - n[0] /= aspx; - n[1] /= aspy; - return; } @@ -531,13 +520,10 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float asp sub_v2_v2v2(vec, r1, r0); - n[0] = -vec[1] * aspy; - n[1] = vec[0] * aspx; + n[0] = -vec[1]; + n[1] = vec[0]; normalize_v2(n); - - n[0] /= aspx; - n[1] /= aspy; } float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 5df91b4032a..01495561912 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -39,6 +39,6 @@ void ED_keymap_mask(struct wmKeyConfig *keyconf); void ED_operatormacros_mask(void); /* mask_draw.c */ -void ED_mask_draw(bContext *C, int width, int height, float zoomx, float zoomy); +void ED_mask_draw(const bContext *C); #endif /* ED_TEXT_H */ diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index e3fe67df16b..152dc6d03da 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -49,12 +49,6 @@ #include "mask_intern.h" /* own include */ -typedef struct PixelSpaceContext { - int width, height; - float zoomx, zoomy; - float aspx, aspy; -} PixelSpaceContext; - static void set_spline_color(MaskShape *shape, MaskSpline *spline) { if (spline->flag & SELECT) { @@ -69,7 +63,7 @@ static void set_spline_color(MaskShape *shape, MaskSpline *spline) } /* return non-zero if spline is selected */ -static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceContext *pixelspace) +static void draw_spline_points(MaskShape *shape, MaskSpline *spline) { int i, hsize, tot_feather_point; float *feather_points, *fp; @@ -82,7 +76,7 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceC glPointSize(hsize); /* feather points */ - feather_points = fp = BKE_mask_spline_feather_points(spline, pixelspace->aspx, pixelspace->aspy, &tot_feather_point); + feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); for (i = 0; i < spline->tot_point; i++) { int j; MaskSplinePoint *point = &spline->points[i]; @@ -119,12 +113,11 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline, PixelSpaceC /* control points */ for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - BezTriple *bezt = &point->bezt; - float vert[2], handle[2]; + float handle[2]; + float *vert = point->bezt.vec[1]; int has_handle = BKE_mask_point_has_handle(point); - copy_v2_v2(vert, bezt->vec[1]); - BKE_mask_point_handle(point, pixelspace->aspx, pixelspace->aspy, handle); + BKE_mask_point_handle(point, handle); /* draw handle segment */ if (has_handle) { @@ -196,7 +189,7 @@ static void draw_dashed_curve(MaskSpline *spline, float *points, int tot_point) glDisable(GL_LINE_STIPPLE); } -static void draw_spline_curve(MaskShape *shape, MaskSpline *spline, PixelSpaceContext *pixelspace) +static void draw_spline_curve(MaskShape *shape, MaskSpline *spline) { float *diff_points, *feather_points; int tot_diff_point, tot_feather_point; @@ -206,8 +199,7 @@ static void draw_spline_curve(MaskShape *shape, MaskSpline *spline, PixelSpaceCo if (!diff_points) return; - feather_points = BKE_mask_spline_feather_differentiated_points(spline, pixelspace->aspx, pixelspace->aspy, - &tot_feather_point); + feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_feather_point); /* draw feather */ if (spline->flag & SELECT) @@ -224,7 +216,7 @@ static void draw_spline_curve(MaskShape *shape, MaskSpline *spline, PixelSpaceCo MEM_freeN(feather_points); } -static void draw_shapes(Mask *mask, PixelSpaceContext *pixelspace) +static void draw_shapes(Mask *mask) { MaskShape *shape = mask->shapes.first; @@ -233,10 +225,10 @@ static void draw_shapes(Mask *mask, PixelSpaceContext *pixelspace) while (spline) { /* draw curve itself first... */ - draw_spline_curve(shape, spline, pixelspace); + draw_spline_curve(shape, spline); /* ...and then handles over the curve so they're nicely visible */ - draw_spline_points(shape, spline, pixelspace); + draw_spline_points(shape, spline); spline = spline->next; } @@ -245,23 +237,12 @@ static void draw_shapes(Mask *mask, PixelSpaceContext *pixelspace) } } -void ED_mask_draw(bContext *C, int width, int height, float zoomx, float zoomy) +void ED_mask_draw(const bContext *C) { Mask *mask = CTX_data_edit_mask(C); - PixelSpaceContext pixelspace; - float aspx, aspy; if (!mask) return; - ED_mask_aspect(C, &aspx, &aspy); - - pixelspace.width = width; - pixelspace.height = height; - pixelspace.zoomx = zoomx; - pixelspace.zoomy = zoomy; - pixelspace.aspx = aspx; - pixelspace.aspy = aspy; - - draw_shapes(mask, &pixelspace); + draw_shapes(mask); } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 5518fedf91a..16f201293d5 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -89,7 +89,7 @@ static void spline_point_select(MaskSplinePoint *point, int action) } -static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, float aspx, float aspy, float start_u, const float co[2]) +static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, float start_u, const float co[2]) { const float proj_eps = 1e-3; const float proj_eps_squared = proj_eps * proj_eps; @@ -104,7 +104,7 @@ static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, fl if (u1 >= 0.0f) { BKE_mask_point_segment_co(spline, point, u1, co1); - BKE_mask_point_normal(spline, point, aspx, aspy, u1, n1); + BKE_mask_point_normal(spline, point, u1, n1); sub_v2_v2v2(v1, co, co1); if (len_squared_v2(v1) > proj_eps_squared) { @@ -125,7 +125,7 @@ static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, fl if (u2 <= 1.0f) { BKE_mask_point_segment_co(spline, point, u2, co2); - BKE_mask_point_normal(spline, point, aspx, aspy, u2, n2); + BKE_mask_point_normal(spline, point, u2, n2); sub_v2_v2v2(v2, co, co2); if (len_squared_v2(v2) > proj_eps_squared) { @@ -249,7 +249,7 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal vec[1] = cur_point->bezt.vec[1][1] * scaley; if (BKE_mask_point_has_handle(cur_point)) { - BKE_mask_point_handle(cur_point, aspx, aspy, handle); + BKE_mask_point_handle(cur_point, handle); handle[0] *= scalex; handle[1] *= scaley; @@ -336,7 +336,7 @@ static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int int i, tot_feather_point; float *feather_points, *fp; - feather_points = fp = BKE_mask_spline_feather_points(spline, aspx, aspy, &tot_feather_point); + feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); for (i = 0; i < spline->tot_point; i++) { int j; @@ -444,7 +444,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], if (feather) { feather_points = BKE_mask_point_segment_feather_diff(spline, cur_point, - aspx, aspy, &tot_feather_point); + &tot_feather_point); points = feather_points; tot_point = tot_feather_point; @@ -502,7 +502,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], *point_r = point; if (u_r) { - u = projection_on_spline(point_spline, point, aspx, aspy, u, normal_co); + u = projection_on_spline(point_spline, point, u, normal_co); *u_r = u; } @@ -748,14 +748,14 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) customdata->weight = uw->w; BKE_mask_point_segment_co(spline, point, uw->u, co); - BKE_mask_point_normal(spline, point, customdata->aspx, customdata->aspy, uw->u, customdata->no); + BKE_mask_point_normal(spline, point, uw->u, customdata->no); customdata->feather[0] = co[0] + customdata->no[0] * uw->w; customdata->feather[1] = co[1] + customdata->no[1] * uw->w; } else { BezTriple *bezt = &point->bezt; - BKE_mask_point_normal(spline, point, customdata->aspx, customdata->aspy, 0.0f, customdata->no); + BKE_mask_point_normal(spline, point, 0.0f, customdata->no); customdata->feather[0] = bezt->vec[1][0] + customdata->no[0] * bezt->weight; customdata->feather[1] = bezt->vec[1][1] + customdata->no[1] * bezt->weight; @@ -763,7 +763,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) copy_m3_m3(customdata->vec, point->bezt.vec); if (BKE_mask_point_has_handle(point)) - BKE_mask_point_handle(point, customdata->aspx, customdata->aspy, customdata->handle); + BKE_mask_point_handle(point, customdata->handle); ED_mask_mouse_pos(C, event, customdata->co); } @@ -882,14 +882,14 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) add_v2_v2v2(offco, data->feather, dco); if (data->uw) { - float u = projection_on_spline(data->spline, data->point, data->aspx, data->aspy, data->uw->u, offco); + float u = projection_on_spline(data->spline, data->point, data->uw->u, offco); if (u > 0.0f && u < 1.0f) data->uw->u = u; data->uw = BKE_mask_point_sort_uw(data->point, data->uw); weight = &data->uw->w; - BKE_mask_point_normal(data->spline, data->point, data->aspx, data->aspy, data->uw->u, no); + BKE_mask_point_normal(data->spline, data->point, data->uw->u, no); BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p); } else { diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 6ebcaf4ea16..8e92a9198b1 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1134,7 +1134,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) glScalef(maxdim * zoomx, maxdim * zoomy, 0); glMultMatrixf(sc->stabmat); - ED_mask_draw((bContext *)C, width*aspx, height*aspy, zoomx, zoomy); + ED_mask_draw((bContext *)C); glPopMatrix(); } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 85d54c0d6e3..50d6beb0681 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5908,7 +5908,7 @@ static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, TransDat else { tdm->is_handle = TRUE; - BKE_mask_point_handle(point, aspx, aspy, tdm->handle); + BKE_mask_point_handle(point, tdm->handle); copy_v2_v2(tdm->orig_handle, tdm->handle); diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 7597a21fd03..dbdde515804 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -54,9 +54,9 @@ typedef struct MaskParent { ID *id; /* ID block of entity to which mask/spline is parented to * in case of parenting to movie tracking data set to MovieClip datablock */ char parent[64]; /* entity of parent to which parenting happened - * in case of parenting to movie tracking data contains name of object */ + * in case of parenting to movie tracking data contains name of object */ char sub_parent[64]; /* sub-entity of parent to which parenting happened - * in case of parenting to movie tracking data contains name of track */ + * in case of parenting to movie tracking data contains name of track */ float offset[2]; /* offset from parent position, so object/control point can be parented to a * motion track and also be animated (see ZanQdo's request below) */ } MaskParent; @@ -96,13 +96,13 @@ typedef struct MaskShape { } MaskShape; /* MaskParent->flag */ -#define MASK_PARENT_ACTIVE (1<<0) +#define MASK_PARENT_ACTIVE (1 << 0) /* MaskSpline->flag */ -#define MASK_SPLINE_CYCLIC (1<<1) +#define MASK_SPLINE_CYCLIC (1 << 1) /* MaskSpline->weight_interp */ -#define MASK_SPLINE_INTERP_LINEAR 1 -#define MASK_SPLINE_INTERP_EASE 2 +#define MASK_SPLINE_INTERP_LINEAR 1 +#define MASK_SPLINE_INTERP_EASE 2 #endif // __DNA_MASK_TYPES_H__ From f82bb6fb4e3a32e727205678eed2457cdd7f12cc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 18 May 2012 10:02:14 +0000 Subject: [PATCH 063/183] fix error with mask translation not quite following the mouse. --- source/blender/editors/transform/transform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 06bcf11bfe4..d06de6be3ae 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -173,7 +173,7 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) if (t->options & CTX_MASK) { /* clamp w/h, mask only */ - divx = divy = minf(divx, divy); + divx = divy = maxf(divx, divy); mulx = muly = minf(mulx, muly); } @@ -181,6 +181,7 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) r_vec[1] = muly * (dy) / divy; r_vec[2] = 0.0f; + /* TODO - NOT WORKING, this isnt so bad since its only display aspect */ if (t->options & CTX_MASK) { float aspx, aspy; ED_space_clip_mask_aspect(t->sa->spacedata.first, &aspx, &aspy); From 837eb6bb182c2020571ded2f4cf155a55e16bd0c Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Fri, 18 May 2012 12:05:10 +0000 Subject: [PATCH 064/183] Support normalization in the tracking prepass The last tracker commit added normalized tracking. This makes tracking patches undergoing uniform illumination change easier. However, the prepass which computes a quick translation-only estimate of the warp did not take this into account. This commit fixes that. This works reasonably well but in some examples the brute initialization fails. I suspect this is due to the warped template estimate in the current frame being too different from the original, so there are multiple peaks in the normalized-SAD correlation function. The solution is to use the previous frame for the brute initialization and the keyframe for refinement, but that requires architecture changes. --- extern/libmv/libmv/tracking/track_region.cc | 67 ++++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index ababd0cee90..6fad3f7af3f 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -19,6 +19,11 @@ // IN THE SOFTWARE. // // Author: mierle@google.com (Keir Mierle) +// +// TODO(keir): While this tracking code works rather well, it has some +// outragous inefficiencies. There is probably a 5-10x speedup to be had if a +// smart coder went through the TODO's and made the suggested performance +// enhancements. // Necessary for M_E when building with MSVC. #define _USE_MATH_DEFINES @@ -868,14 +873,17 @@ bool PointOnRightHalfPlane(const Vec2 &a, const Vec2 &b, double x, double y) { // Determine if a point is in a quad. The quad is arranged as: // -// +--> x +// +-------> x // | -// | 0 1 -// v 3 2 +// | a0------a1 +// | | | +// | | | +// | | | +// | a3------a2 +// v // y // -// The idea is to take the maximum x or y distance. This may be oversampling. -// TODO(keir): Investigate the various choices; perhaps average is better? +// The implementation does up to four half-plane comparisons. bool PointInQuad(const double *xs, const double *ys, double x, double y) { Vec2 a0(xs[0], ys[0]); Vec2 a1(xs[1], ys[1]); @@ -888,6 +896,8 @@ bool PointInQuad(const double *xs, const double *ys, double x, double y) { PointOnRightHalfPlane(a3, a0, x, y); } +// This makes it possible to map between Eigen float arrays and FloatImage +// without using comparisons. typedef Eigen::Array FloatArray; // This creates a pattern in the frame of image2, from the pixel is image1, @@ -946,11 +956,26 @@ void CreateBrutePattern(const double *x1, const double *y1, *origin_y = min_y; } +// Compute a translation-only estimate of the warp, using brute force search. A +// smarter implementation would use the FFT to compute the normalized cross +// correlation. Instead, this is a dumb implementation. Surprisingly, it is +// fast enough in practice. +// +// TODO(keir): The normalization is less effective for the brute force search +// than it is with the Ceres solver. It's unclear if this is a bug or due to +// the original frame being too different from the reprojected reference in the +// destination frame. +// +// The likely solution is to use the previous frame, instead of the original +// pattern, when doing brute initialization. Unfortunately that implies a +// totally different warping interface, since access to more than a the source +// and current destination frame is necessary. template void BruteTranslationOnlyInitialize(const FloatImage &image1, const FloatImage *image1_mask, const FloatImage &image2, const int num_extra_points, + const bool use_normalized_intensities, const double *x1, const double *y1, double *x2, double *y2) { // Create the pattern to match in the space of image2, assuming our inital @@ -959,8 +984,18 @@ void BruteTranslationOnlyInitialize(const FloatImage &image1, FloatArray pattern; FloatArray mask; int origin_x = -1, origin_y = -1; - CreateBrutePattern(x1, y1, x2, y2, image1, image1_mask, - &pattern, &mask, &origin_x, &origin_y); + CreateBrutePattern(x1, y1, x2, y2, + image1, image1_mask, + &pattern, &mask, + &origin_x, &origin_y); + + // For normalization, premultiply the pattern by the inverse pattern mean. + double mask_sum = 1.0; + if (use_normalized_intensities) { + mask_sum = mask.sum(); + double inverse_pattern_mean = mask_sum / ((mask * pattern).sum()); + pattern *= inverse_pattern_mean; + } // Use Eigen on the images via maps for strong vectorization. Map search(image2.Data(), image2.Height(), image2.Width()); @@ -984,8 +1019,21 @@ void BruteTranslationOnlyInitialize(const FloatImage &image1, int h = pattern.rows(); for (int r = 0; r < (image2.Height() - h); ++r) { for (int c = 0; c < (image2.Width() - w); ++c) { - // Compute the weighted sum of absolute differences, Eigen style. - double sad = (mask * (pattern - search.block(r, c, h, w))).abs().sum(); + // Compute the weighted sum of absolute differences, Eigen style. Note + // that the block from the search image is never stored in a variable, to + // avoid copying overhead and permit inlining. + double sad; + if (use_normalized_intensities) { + // TODO(keir): It's really dumb to recompute the search mean for every + // shift. A smarter implementation would use summed area tables + // instead, reducing the mean calculation to an O(1) operation. + double inverse_search_mean = + mask_sum / ((mask * search.block(r, c, h, w)).sum()); + sad = (mask * (pattern - (search.block(r, c, h, w) * + inverse_search_mean))).abs().sum(); + } else { + sad = (mask * (pattern - search.block(r, c, h, w))).abs().sum(); + } if (sad < best_sad) { best_r = r; best_c = c; @@ -1053,6 +1101,7 @@ void TemplatedTrackRegion(const FloatImage &image1, options.image1_mask, image2, options.num_extra_points, + options.use_normalized_intensities, x1, y1, x2, y2); for (int i = 0; i < 4; ++i) { LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); brute (" From 2870366d72df618fa4ea267cc0c33a1f66fd04df Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 18 May 2012 12:51:11 +0000 Subject: [PATCH 065/183] rename 'mask shape' to mask object, will make adding shape keys less confusing. --- release/scripts/startup/bl_ui/space_clip.py | 22 +- source/blender/blenkernel/BKE_mask.h | 18 +- source/blender/blenkernel/intern/mask.c | 88 +++--- source/blender/blenloader/intern/readfile.c | 28 +- source/blender/blenloader/intern/writefile.c | 12 +- source/blender/editors/mask/mask_draw.c | 34 +-- source/blender/editors/mask/mask_editor.c | 6 +- source/blender/editors/mask/mask_intern.h | 4 +- source/blender/editors/mask/mask_ops.c | 254 +++++++++--------- .../editors/transform/transform_conversions.c | 18 +- source/blender/makesdna/DNA_mask_types.h | 16 +- source/blender/makesrna/intern/rna_mask.c | 176 ++++++------ .../composite/nodes/node_composite_mask.c | 10 +- 13 files changed, 343 insertions(+), 343 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 90b3901c002..c6ea5633f23 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -555,10 +555,10 @@ class CLIP_PT_tracking_camera(Panel): col.prop(clip.tracking.camera, "k3") -class CLIP_PT_shapes(Panel): +class CLIP_PT_mask_objects(Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' - bl_label = "Shapes" + bl_label = "Mask Objects" @classmethod def poll(cls, context): @@ -573,15 +573,15 @@ class CLIP_PT_shapes(Panel): mask = sc.mask row = layout.row() - row.template_list(mask, "shapes", - mask, "active_shape_index", rows=3) + row.template_list(mask, "objects", + mask, "active_object_index", rows=3) sub = row.column(align=True) - sub.operator("mask.shape_new", icon='ZOOMIN', text="") - sub.operator("mask.shape_remove", icon='ZOOMOUT', text="") + sub.operator("mask.object_new", icon='ZOOMIN', text="") + sub.operator("mask.object_remove", icon='ZOOMOUT', text="") - active = mask.shapes.active + active = mask.objects.active if active: layout.prop(active, "name") @@ -597,7 +597,7 @@ class CLIP_PT_active_mask_spline(Panel): mask = sc.mask if mask and sc.mode == 'MASKEDITING': - return mask.shapes.active and mask.shapes.active.splines.active + return mask.objects.active and mask.objects.active.splines.active return False @@ -606,7 +606,7 @@ class CLIP_PT_active_mask_spline(Panel): sc = context.space_data mask = sc.mask - spline = mask.shapes.active.splines.active + spline = mask.objects.active.splines.active col = layout.column() col.prop(spline, "weight_interpolation") @@ -624,7 +624,7 @@ class CLIP_PT_active_mask_point(Panel): mask = sc.mask if mask and sc.mode == 'MASKEDITING': - return mask.shapes.active and mask.shapes.active.splines.active_point + return mask.objects.active and mask.objects.active.splines.active_point return False @@ -633,7 +633,7 @@ class CLIP_PT_active_mask_point(Panel): sc = context.space_data mask = sc.mask - point = mask.shapes.active.splines.active_point + point = mask.objects.active.splines.active_point parent = point.parent col = layout.column() diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 88934e4af84..361de2c38ce 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -30,7 +30,7 @@ struct Main; struct Mask; struct MaskParent; -struct MaskShape; +struct MaskObject; struct MaskSpline; struct MaskSplinePoint; struct MaskSplinePointUW; @@ -38,20 +38,20 @@ struct MovieClip; struct MovieClipUser; struct Scene; -/* shapes */ -struct MaskShape *BKE_mask_shape_new(struct Mask *mask, const char *name); -struct MaskShape *BKE_mask_shape_active(struct Mask *mask); -void BKE_mask_shape_active_set(struct Mask *mask, struct MaskShape *shape); -void BKE_mask_shape_remove(struct Mask *mask, struct MaskShape *shape); +/* mask objects */ +struct MaskObject *BKE_mask_object_new(struct Mask *mask, const char *name); +struct MaskObject *BKE_mask_object_active(struct Mask *mask); +void BKE_mask_object_active_set(struct Mask *mask, struct MaskObject *maskobj); +void BKE_mask_object_remove(struct Mask *mask, struct MaskObject *maskobj); -void BKE_mask_shape_free(struct MaskShape *shape); +void BKE_mask_object_free(struct MaskObject *maskobj); void BKE_mask_spline_free(struct MaskSpline *spline); void BKE_mask_point_free(struct MaskSplinePoint *point); -void BKE_mask_shape_unique_name(struct Mask *mask, struct MaskShape *shape); +void BKE_mask_object_unique_name(struct Mask *mask, struct MaskObject *maskobj); /* splines */ -struct MaskSpline *BKE_mask_spline_add(struct MaskShape *shape); +struct MaskSpline *BKE_mask_spline_add(struct MaskObject *maskobj); int BKE_mask_spline_resolution(struct MaskSpline *spline); float *BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point); float *BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 863945e6baf..e3c2570ab93 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -55,68 +55,68 @@ #include "BKE_movieclip.h" #include "BKE_utildefines.h" -/* shapes */ +/* mask objects */ -MaskShape *BKE_mask_shape_new(Mask *mask, const char *name) +MaskObject *BKE_mask_object_new(Mask *mask, const char *name) { - MaskShape *shape = MEM_callocN(sizeof(MaskShape), "new mask shape"); + MaskObject *maskobj = MEM_callocN(sizeof(MaskObject), "new mask object"); if (name && name[0]) - BLI_strncpy(shape->name, name, sizeof(shape->name)); + BLI_strncpy(maskobj->name, name, sizeof(maskobj->name)); else - strcpy(shape->name, "Shape"); + strcpy(maskobj->name, "MaskObject"); - BLI_addtail(&mask->shapes, shape); + BLI_addtail(&mask->maskobjs, maskobj); - BKE_mask_shape_unique_name(mask, shape); + BKE_mask_object_unique_name(mask, maskobj); - mask->tot_shape++; + mask->tot_maskobj++; - return shape; + return maskobj; } -MaskShape *BKE_mask_shape_active(Mask *mask) +MaskObject *BKE_mask_object_active(Mask *mask) { - return BLI_findlink(&mask->shapes, mask->shapenr); + return BLI_findlink(&mask->maskobjs, mask->act_maskobj); } -void BKE_mask_shape_active_set(Mask *mask, MaskShape *shape) +void BKE_mask_object_active_set(Mask *mask, MaskObject *maskobj) { - int index = BLI_findindex(&mask->shapes, shape); + int index = BLI_findindex(&mask->maskobjs, maskobj); if (index >= 0) - mask->shapenr = index; + mask->act_maskobj = index; else - mask->shapenr = 0; + mask->act_maskobj = 0; } -void BKE_mask_shape_remove(Mask *mask, MaskShape *shape) +void BKE_mask_object_remove(Mask *mask, MaskObject *maskobj) { - BLI_remlink(&mask->shapes, shape); - BKE_mask_shape_free(shape); + BLI_remlink(&mask->maskobjs, maskobj); + BKE_mask_object_free(maskobj); - mask->tot_shape--; + mask->tot_maskobj--; - if (mask->shapenr >= mask->tot_shape) - mask->shapenr = mask->tot_shape - 1; + if (mask->act_maskobj >= mask->tot_maskobj) + mask->act_maskobj = mask->tot_maskobj - 1; } -void BKE_mask_shape_unique_name(Mask *mask, MaskShape *shape) +void BKE_mask_object_unique_name(Mask *mask, MaskObject *maskobj) { - BLI_uniquename(&mask->shapes, shape, "Shape", '.', offsetof(MaskShape, name), sizeof(shape->name)); + BLI_uniquename(&mask->maskobjs, maskobj, "MaskObject", '.', offsetof(MaskObject, name), sizeof(maskobj->name)); } /* splines */ -MaskSpline *BKE_mask_spline_add(MaskShape *shape) +MaskSpline *BKE_mask_spline_add(MaskObject *maskobj) { MaskSpline *spline; - spline = MEM_callocN(sizeof(MaskSpline), "new shape spline"); - BLI_addtail(&shape->splines, spline); + spline = MEM_callocN(sizeof(MaskSpline), "new mask spline"); + BLI_addtail(&maskobj->splines, spline); /* spline shall have one point at least */ - spline->points = MEM_callocN(sizeof(MaskSplinePoint), "new shape spline point"); + spline->points = MEM_callocN(sizeof(MaskSplinePoint), "new mask spline point"); spline->tot_point = 1; /* cyclic shapes are more usually used */ @@ -662,33 +662,33 @@ void BKE_mask_spline_free(MaskSpline *spline) MEM_freeN(spline); } -void BKE_mask_shape_free(MaskShape *shape) +void BKE_mask_object_free(MaskObject *maskobj) { - MaskSpline *spline = shape->splines.first; + MaskSpline *spline = maskobj->splines.first; while (spline) { MaskSpline *next_spline = spline->next; - BLI_remlink(&shape->splines, spline); + BLI_remlink(&maskobj->splines, spline); BKE_mask_spline_free(spline); spline = next_spline; } - MEM_freeN(shape); + MEM_freeN(maskobj); } void BKE_mask_free(Mask *mask) { - MaskShape *shape = mask->shapes.first; + MaskObject *maskobj = mask->maskobjs.first; - while (shape) { - MaskShape *next_shape = shape->next; + while (maskobj) { + MaskObject *next_maskobj = maskobj->next; - BLI_remlink(&mask->shapes, shape); - BKE_mask_shape_free(shape); + BLI_remlink(&mask->maskobjs, maskobj); + BKE_mask_object_free(maskobj); - shape = next_shape; + maskobj = next_maskobj; } } @@ -940,12 +940,12 @@ void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplineP void BKE_mask_calc_handles(Mask *mask) { - MaskShape *shape; + MaskObject *maskobj; - for (shape = mask->shapes.first; shape; shape = shape->next) { + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - for (spline = shape->splines.first; spline; spline = spline->next) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -957,10 +957,10 @@ void BKE_mask_calc_handles(Mask *mask) void BKE_mask_evaluate(Mask *mask, float ctime) { - MaskShape *shape = mask->shapes.first; + MaskObject *maskobj = mask->maskobjs.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; int i; while (spline) { @@ -981,7 +981,7 @@ void BKE_mask_evaluate(Mask *mask, float ctime) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } BKE_mask_calc_handles(mask); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2e30f756b43..d0b9808697f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6276,19 +6276,19 @@ static void lib_link_movieclip(FileData *fd, Main *main) static void direct_link_mask(FileData *fd, Mask *mask) { - MaskShape *shape; + MaskObject *maskobj; mask->adt = newdataadr(fd, mask->adt); - link_list(fd, &mask->shapes); + link_list(fd, &mask->maskobjs); - shape = mask->shapes.first; - while (shape) { + maskobj = mask->maskobjs.first; + while (maskobj) { MaskSpline *spline; - link_list(fd, &shape->splines); + link_list(fd, &maskobj->splines); - spline = shape->splines.first; + spline = maskobj->splines.first; while (spline) { int i; @@ -6304,10 +6304,10 @@ static void direct_link_mask(FileData *fd, Mask *mask) spline = spline->next; } - shape->act_spline = newdataadr(fd, shape->act_spline); - shape->act_point = newdataadr(fd, shape->act_point); + maskobj->act_spline = newdataadr(fd, maskobj->act_spline); + maskobj->act_point = newdataadr(fd, maskobj->act_point); - shape = shape->next; + maskobj = maskobj->next; } } @@ -6323,16 +6323,16 @@ static void lib_link_mask(FileData *fd, Main *main) mask = main->mask.first; while (mask) { if(mask->id.flag & LIB_NEEDLINK) { - MaskShape *shape; + MaskObject *maskobj; if (mask->adt) lib_link_animdata(fd, &mask->id, mask->adt); - shape = mask->shapes.first; - while (shape) { + maskobj = mask->maskobjs.first; + while (maskobj) { MaskSpline *spline; - spline = shape->splines.first; + spline = maskobj->splines.first; while (spline) { int i; @@ -6347,7 +6347,7 @@ static void lib_link_mask(FileData *fd, Main *main) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } mask->id.flag -= LIB_NEEDLINK; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 539b19c5561..a514a3283b1 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2762,20 +2762,20 @@ static void write_masks(WriteData *wd, ListBase *idbase) mask = idbase->first; while (mask) { if (mask->id.us > 0 || wd->current) { - MaskShape *shape; + MaskObject *maskobj; writestruct(wd, ID_MSK, "Mask", 1, mask); if (mask->adt) write_animdata(wd, mask->adt); - shape = mask->shapes.first; - while (shape) { + maskobj = mask->maskobjs.first; + while (maskobj) { MaskSpline *spline; - writestruct(wd, DATA, "MaskShape", 1, shape); + writestruct(wd, DATA, "MaskObject", 1, maskobj); - spline = shape->splines.first; + spline = maskobj->splines.first; while (spline) { int i; @@ -2792,7 +2792,7 @@ static void write_masks(WriteData *wd, ListBase *idbase) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 152dc6d03da..06f24c6fa8f 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -49,10 +49,10 @@ #include "mask_intern.h" /* own include */ -static void set_spline_color(MaskShape *shape, MaskSpline *spline) +static void set_spline_color(MaskObject *maskobj, MaskSpline *spline) { if (spline->flag & SELECT) { - if (shape->act_spline == spline) + if (maskobj->act_spline == spline) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 0.0f, 0.0f); @@ -63,7 +63,7 @@ static void set_spline_color(MaskShape *shape, MaskSpline *spline) } /* return non-zero if spline is selected */ -static void draw_spline_points(MaskShape *shape, MaskSpline *spline) +static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) { int i, hsize, tot_feather_point; float *feather_points, *fp; @@ -92,7 +92,7 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline) } if (sel) { - if (point == shape->act_point) + if (point == maskobj->act_point) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); @@ -121,7 +121,7 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline) /* draw handle segment */ if (has_handle) { - set_spline_color(shape, spline); + set_spline_color(maskobj, spline); glBegin(GL_LINES); glVertex3fv(vert); @@ -131,7 +131,7 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline) /* draw CV point */ if (MASKPOINT_CV_ISSEL(point)) { - if (point == shape->act_point) + if (point == maskobj->act_point) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); @@ -146,7 +146,7 @@ static void draw_spline_points(MaskShape *shape, MaskSpline *spline) /* draw handle points */ if (has_handle) { if (MASKPOINT_HANDLE_ISSEL(point)) { - if (point == shape->act_point) + if (point == maskobj->act_point) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); @@ -189,7 +189,7 @@ static void draw_dashed_curve(MaskSpline *spline, float *points, int tot_point) glDisable(GL_LINE_STIPPLE); } -static void draw_spline_curve(MaskShape *shape, MaskSpline *spline) +static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline) { float *diff_points, *feather_points; int tot_diff_point, tot_feather_point; @@ -209,31 +209,31 @@ static void draw_spline_curve(MaskShape *shape, MaskSpline *spline) draw_dashed_curve(spline, feather_points, tot_feather_point); /* draw main curve */ - set_spline_color(shape, spline); + set_spline_color(maskobj, spline); draw_dashed_curve(spline, diff_points, tot_diff_point); MEM_freeN(diff_points); MEM_freeN(feather_points); } -static void draw_shapes(Mask *mask) +static void draw_maskobjs(Mask *mask) { - MaskShape *shape = mask->shapes.first; + MaskObject *maskobj = mask->maskobjs.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { /* draw curve itself first... */ - draw_spline_curve(shape, spline); + draw_spline_curve(maskobj, spline); /* ...and then handles over the curve so they're nicely visible */ - draw_spline_points(shape, spline); + draw_spline_points(maskobj, spline); spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } } @@ -244,5 +244,5 @@ void ED_mask_draw(const bContext *C) if (!mask) return; - draw_shapes(mask); + draw_maskobjs(mask); } diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index a868696941c..e8311935d86 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -146,9 +146,9 @@ void ED_operatortypes_mask(void) { WM_operatortype_append(MASK_OT_new); - /* shapes */ - WM_operatortype_append(MASK_OT_shape_new); - WM_operatortype_append(MASK_OT_shape_remove); + /* mask objects */ + WM_operatortype_append(MASK_OT_object_new); + WM_operatortype_append(MASK_OT_object_remove); /* geometry */ WM_operatortype_append(MASK_OT_add_vertex); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 073eba3efc9..163239eade7 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -40,8 +40,8 @@ struct wmOperatorType; /* mask_ops.c */ void MASK_OT_new(struct wmOperatorType *ot); -void MASK_OT_shape_new(struct wmOperatorType *ot); -void MASK_OT_shape_remove(struct wmOperatorType *ot); +void MASK_OT_object_new(struct wmOperatorType *ot); +void MASK_OT_object_remove(struct wmOperatorType *ot); void MASK_OT_add_vertex(struct wmOperatorType *ot); void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 16f201293d5..9b9dbcec7e5 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -167,10 +167,10 @@ static int points_has_selection(MaskSplinePoint *points, int tot_point) static int mask_has_selection(Mask *mask) { - MaskShape *shape = mask->shapes.first; + MaskObject *maskobj = mask->maskobjs.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { if (points_has_selection(spline->points, spline->tot_point)) @@ -179,7 +179,7 @@ static int mask_has_selection(Mask *mask) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } return FALSE; @@ -187,7 +187,7 @@ static int mask_has_selection(Mask *mask) static void toggle_selection_all(Mask *mask, int action) { - MaskShape *shape = mask->shapes.first; + MaskObject *maskobj = mask->maskobjs.first; if (action == SEL_TOGGLE) { if (mask_has_selection(mask)) @@ -196,8 +196,8 @@ static void toggle_selection_all(Mask *mask, int action) action = SEL_SELECT; } - while (shape) { - MaskSpline *spline = shape->splines.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { int i; @@ -211,16 +211,16 @@ static void toggle_selection_all(Mask *mask, int action) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } } static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal_co[2], int threshold, - MaskShape **shape_r, MaskSpline **spline_r, int *is_handle_r, + MaskObject **maskobj_r, MaskSpline **spline_r, int *is_handle_r, float *score) { - MaskShape *shape; - MaskShape *point_shape = NULL; + MaskObject *maskobj; + MaskObject *point_maskobj = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; float co[2], aspx, aspy; @@ -234,9 +234,9 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - shape = mask->shapes.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + maskobj = mask->maskobjs.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { int i; @@ -256,7 +256,7 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal cur_len = len_v2v2(co, handle); if (cur_len < len) { - point_shape = shape; + point_maskobj = maskobj; point_spline = spline; point = cur_point; len = cur_len; @@ -268,7 +268,7 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal if (cur_len < len) { point_spline = spline; - point_shape = shape; + point_maskobj = maskobj; point = cur_point; len = cur_len; is_handle = FALSE; @@ -278,12 +278,12 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } if (len < threshold) { - if (shape_r) - *shape_r = point_shape; + if (maskobj_r) + *maskobj_r = point_maskobj; if (spline_r) *spline_r = point_spline; @@ -297,8 +297,8 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal return point; } - if (shape_r) - *shape_r = NULL; + if (maskobj_r) + *maskobj_r = NULL; if (spline_r) *spline_r = NULL; @@ -310,10 +310,10 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal } static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int threshold, - MaskShape **shape_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + MaskObject **maskobj_r, MaskSpline **spline_r, MaskSplinePoint **point_r, MaskSplinePointUW **uw_r, float *score) { - MaskShape *shape, *point_shape = NULL; + MaskObject *maskobj, *point_maskobj = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; MaskSplinePointUW *uw = NULL; @@ -328,9 +328,9 @@ static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - shape = mask->shapes.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + maskobj = mask->maskobjs.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { int i, tot_feather_point; @@ -356,7 +356,7 @@ static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int else uw = &cur_point->uw[j - 1]; - point_shape = shape; + point_maskobj = maskobj; point_spline = spline; point = cur_point; len = cur_len; @@ -371,12 +371,12 @@ static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } if (len < threshold) { - if (shape_r) - *shape_r = point_shape; + if (maskobj_r) + *maskobj_r = point_maskobj; if (spline_r) *spline_r = point_spline; @@ -393,8 +393,8 @@ static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int return TRUE; } - if (shape_r) - *shape_r = NULL; + if (maskobj_r) + *maskobj_r = NULL; if (spline_r) *spline_r = NULL; @@ -406,10 +406,10 @@ static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int } static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], int threshold, int feather, - MaskShape **shape_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + MaskObject **maskobj_r, MaskSpline **spline_r, MaskSplinePoint **point_r, float *u_r, float tangent[2]) { - MaskShape *shape, *point_shape; + MaskObject *maskobj, *point_maskobj; MaskSpline *point_spline; MaskSplinePoint *point = NULL; float dist, co[2]; @@ -424,9 +424,9 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - shape = mask->shapes.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + maskobj = mask->maskobjs.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { int i; @@ -469,7 +469,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], if (tangent) sub_v2_v2v2(tangent, &diff_points[2 * i + 2], &diff_points[2 * i]); - point_shape = shape; + point_maskobj = maskobj; point_spline = spline; point = cur_point; dist = cur_dist; @@ -488,12 +488,12 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } if (point && dist < threshold) { - if (shape_r) - *shape_r = point_shape; + if (maskobj_r) + *maskobj_r = point_maskobj; if (spline_r) *spline_r = point_spline; @@ -510,8 +510,8 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], return TRUE; } - if (shape_r) - *shape_r = NULL; + if (maskobj_r) + *maskobj_r = NULL; if (spline_r) *spline_r = NULL; @@ -524,11 +524,11 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], static void mask_flush_selection(Mask *mask) { - MaskShape *shape; + MaskObject *maskobj; - shape = mask->shapes.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + maskobj = mask->maskobjs.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { int i; @@ -556,7 +556,7 @@ static void mask_flush_selection(Mask *mask) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } } @@ -596,50 +596,50 @@ void MASK_OT_new(wmOperatorType *ot) RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask"); } -/******************** create new shape *********************/ +/******************** create new maskobj *********************/ -static int shape_new_exec(bContext *C, wmOperator *op) +static int maskobj_new_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); char name[MAX_ID_NAME - 2]; RNA_string_get(op->ptr, "name", name); - BKE_mask_shape_new(mask, name); - mask->shapenr = mask->tot_shape - 1; + BKE_mask_object_new(mask, name); + mask->act_maskobj = mask->tot_maskobj - 1; WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; } -void MASK_OT_shape_new(wmOperatorType *ot) +void MASK_OT_object_new(wmOperatorType *ot) { /* identifiers */ - ot->name = "Add Shape"; - ot->description = "Add new shape for masking"; - ot->idname = "MASK_OT_shape_new"; + ot->name = "Add Mask Object"; + ot->description = "Add new mask object for masking"; + ot->idname = "MASK_OT_object_new"; /* api callbacks */ - ot->exec = shape_new_exec; + ot->exec = maskobj_new_exec; ot->poll = ED_maskediting_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new shape"); + RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask object"); } -/******************** remove shape *********************/ +/******************** remove mask object *********************/ -static int shape_remove_exec(bContext *C, wmOperator *UNUSED(op)) +static int maskobj_remove_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskShape *shape = BKE_mask_shape_active(mask); + MaskObject *maskobj = BKE_mask_object_active(mask); - if (shape) { - BKE_mask_shape_remove(mask, shape); + if (maskobj) { + BKE_mask_object_remove(mask, maskobj); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); } @@ -647,15 +647,15 @@ static int shape_remove_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -void MASK_OT_shape_remove(wmOperatorType *ot) +void MASK_OT_object_remove(wmOperatorType *ot) { /* identifiers */ - ot->name = "Remove Shape"; - ot->description = "Remove shape used for masking"; - ot->idname = "MASK_OT_shape_remove"; + ot->name = "Remove Mask Object"; + ot->description = "Remove mask object"; + ot->idname = "MASK_OT_object_remove"; /* api callbacks */ - ot->exec = shape_remove_exec; + ot->exec = maskobj_remove_exec; ot->poll = ED_maskediting_poll; /* flags */ @@ -676,7 +676,7 @@ typedef struct SlidePointData { float vec[3][3]; Mask *mask; - MaskShape *shape; + MaskObject *maskobj; MaskSpline *spline; MaskSplinePoint *point; MaskSplinePointUW *uw; @@ -692,7 +692,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) { Mask *mask = CTX_data_edit_mask(C); SlidePointData *customdata = NULL; - MaskShape *shape, *cv_shape, *feather_shape; + MaskObject *maskobj, *cv_maskobj, *feather_maskobj; MaskSpline *spline, *cv_spline, *feather_spline; MaskSplinePoint *point, *cv_point, *feather_point; MaskSplinePointUW *uw = NULL; @@ -704,13 +704,13 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) ED_mask_mouse_pos(C, event, co); ED_mask_size(C, &width, &height); - cv_point = find_nearest_point(C, mask, co, threshold, &cv_shape, &cv_spline, &is_handle, &cv_score); + cv_point = find_nearest_point(C, mask, co, threshold, &cv_maskobj, &cv_spline, &is_handle, &cv_score); - if (find_nearest_feather(C, mask, co, threshold, &feather_shape, &feather_spline, &feather_point, &uw, &feather_score)) { + if (find_nearest_feather(C, mask, co, threshold, &feather_maskobj, &feather_spline, &feather_point, &uw, &feather_score)) { if (slide_feather || !cv_point || feather_score < cv_score) { action = SLIDE_ACTION_FEATHER; - shape = feather_shape; + maskobj = feather_maskobj; spline = feather_spline; point = feather_point; } @@ -722,7 +722,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) else action = SLIDE_ACTION_POINT; - shape = cv_shape; + maskobj = cv_maskobj; spline = cv_spline; point = cv_point; } @@ -731,7 +731,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data"); customdata->mask = mask; - customdata->shape = shape; + customdata->maskobj = maskobj; customdata->spline = spline; customdata->point = point; customdata->width = width; @@ -798,8 +798,8 @@ static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) mask_flush_selection(mask); } - slidedata->shape->act_spline = slidedata->spline; - slidedata->shape->act_point = slidedata->point; + slidedata->maskobj->act_spline = slidedata->spline; + slidedata->maskobj->act_point = slidedata->point; WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); @@ -999,7 +999,7 @@ void MASK_OT_select_all(wmOperatorType *ot) static int select_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskShape *shape; + MaskObject *maskobj; MaskSpline *spline; MaskSplinePoint *point = NULL; float co[2]; @@ -1009,7 +1009,7 @@ static int select_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "location", co); - point = find_nearest_point(C, mask, co, threshold, &shape, &spline, &is_handle, NULL); + point = find_nearest_point(C, mask, co, threshold, &maskobj, &spline, &is_handle, NULL); if (point) { if (!extend) @@ -1022,8 +1022,8 @@ static int select_exec(bContext *C, wmOperator *op) spline_point_select(point, SEL_SELECT); } - shape->act_spline = spline; - shape->act_point = point; + maskobj->act_spline = spline; + maskobj->act_point = point; mask_flush_selection(mask); @@ -1032,14 +1032,14 @@ static int select_exec(bContext *C, wmOperator *op) else { MaskSplinePointUW *uw; - if (find_nearest_feather(C, mask, co, threshold, &shape, &spline, &point, &uw, NULL)) { + if (find_nearest_feather(C, mask, co, threshold, &maskobj, &spline, &point, &uw, NULL)) { if (!extend) toggle_selection_all(mask, SEL_DESELECT); uw->flag |= SELECT; - shape->act_spline = spline; - shape->act_point = point; + maskobj->act_spline = spline; + maskobj->act_point = point; mask_flush_selection(mask); @@ -1217,13 +1217,13 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) { - MaskShape *shape; + MaskObject *maskobj; MaskSpline *spline; MaskSplinePoint *point = NULL; const float threshold = 9; float tangent[2]; - if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &shape, &spline, &point, NULL, tangent)) { + if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &maskobj, &spline, &point, NULL, tangent)) { MaskSplinePoint *new_point_array, *new_point; int point_index = point - spline->points; @@ -1243,7 +1243,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) setup_vertex_point(C, mask, spline, new_point, co, tangent, NULL, TRUE); - shape->act_point = new_point; + maskobj->act_point = new_point; WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1255,17 +1255,17 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) /* **** add extrude vertex **** */ -static void finSelectedSplinePoint(MaskShape *shape, MaskSpline **spline, MaskSplinePoint **point, short check_active) +static void finSelectedSplinePoint(MaskObject *maskobj, MaskSpline **spline, MaskSplinePoint **point, short check_active) { - MaskSpline *cur_spline = shape->splines.first; + MaskSpline *cur_spline = maskobj->splines.first; *spline = NULL; *point = NULL; if (check_active) { - if (shape->act_spline && shape->act_point) { - *spline = shape->act_spline; - *point = shape->act_point; + if (maskobj->act_spline && maskobj->act_point) { + *spline = maskobj->act_spline; + *point = maskobj->act_point; return; } } @@ -1298,30 +1298,30 @@ static void finSelectedSplinePoint(MaskShape *shape, MaskSpline **spline, MaskSp static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) { - MaskShape *shape; + MaskObject *maskobj; MaskSpline *spline; MaskSplinePoint *point; MaskSplinePoint *new_point = NULL, *ref_point = NULL; toggle_selection_all(mask, SEL_DESELECT); - shape = BKE_mask_shape_active(mask); + maskobj = BKE_mask_object_active(mask); - if (!shape) { - /* if there's no shape currently operationg on, create new one */ - shape = BKE_mask_shape_new(mask, ""); - mask->shapenr = mask->tot_shape - 1; + if (!maskobj) { + /* if there's no maskobj currently operationg on, create new one */ + maskobj = BKE_mask_object_new(mask, ""); + mask->act_maskobj = mask->tot_maskobj - 1; spline = NULL; point = NULL; } else { - finSelectedSplinePoint(shape, &spline, &point, TRUE); + finSelectedSplinePoint(maskobj, &spline, &point, TRUE); } if (!spline) { - /* no selected splines in actuve shape, create new spline */ - spline = BKE_mask_spline_add(shape); - shape->act_spline = spline; + /* no selected splines in active maskobj, create new spline */ + spline = BKE_mask_spline_add(maskobj); + maskobj->act_spline = spline; new_point = spline->points; } @@ -1351,13 +1351,13 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) ref_point = &spline->points[1]; } else { - spline = BKE_mask_spline_add(shape); - shape->act_spline = spline; + spline = BKE_mask_spline_add(maskobj); + maskobj->act_spline = spline; new_point = spline->points; } } - shape->act_point = new_point; + maskobj->act_point = new_point; setup_vertex_point(C, mask, spline, new_point, co, NULL, ref_point, FALSE); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1416,7 +1416,7 @@ void MASK_OT_add_vertex(wmOperatorType *ot) static int add_feather_vertex_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskShape *shape; + MaskObject *maskobj; MaskSpline *spline; MaskSplinePoint *point = NULL; const float threshold = 9; @@ -1428,7 +1428,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) if (point) return OPERATOR_FINISHED; - if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &shape, &spline, &point, &u, NULL)) { + if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &maskobj, &spline, &point, &u, NULL)) { float w = BKE_mask_point_weight(spline, point, u); BKE_mask_point_add_uw(point, u, w); @@ -1477,10 +1477,10 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot) static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskShape *shape = mask->shapes.first; + MaskObject *maskobj = mask->maskobjs.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { if (points_has_selection(spline->points, spline->tot_point)) @@ -1489,7 +1489,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1553,10 +1553,10 @@ static void delete_feather_points(MaskSplinePoint *point) static int delete_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskShape *shape = mask->shapes.first; + MaskObject *maskobj = mask->maskobjs.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { int i, count = 0; @@ -1572,12 +1572,12 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) if (count == 0) { /* delete the whole spline */ - BLI_remlink(&shape->splines, spline); + BLI_remlink(&maskobj->splines, spline); BKE_mask_spline_free(spline); - if (spline == shape->act_spline) { - shape->act_spline = NULL; - shape->act_point = NULL; + if (spline == maskobj->act_spline) { + maskobj->act_spline = NULL; + maskobj->act_point = NULL; } } else { @@ -1590,8 +1590,8 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) MaskSplinePoint *point = &spline->points[i]; if (!MASKPOINT_ISSEL(point)) { - if (point == shape->act_point) - shape->act_point = &new_points[j]; + if (point == maskobj->act_point) + maskobj->act_point = &new_points[j]; delete_feather_points(point); @@ -1599,8 +1599,8 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) j++; } else { - if (point == shape->act_point) - shape->act_point = NULL; + if (point == maskobj->act_point) + maskobj->act_point = NULL; BKE_mask_point_free(point); } @@ -1616,7 +1616,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) spline = next_spline; } - shape = shape->next; + maskobj = maskobj->next; } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1645,11 +1645,11 @@ void MASK_OT_delete(wmOperatorType *ot) static int set_handle_type_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskShape *shape = mask->shapes.first; + MaskObject *maskobj = mask->maskobjs.first; int handle_type = RNA_enum_get(op->ptr, "type"); - while (shape) { - MaskSpline *spline = shape->splines.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; int i; while (spline) { @@ -1666,7 +1666,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 50d6beb0681..0a4b7aaeb01 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5943,15 +5943,15 @@ static void createTransMaskingData(bContext *C, TransInfo *t) { SpaceClip *sc = CTX_wm_space_clip(C); Mask *mask = CTX_data_edit_mask(C); - MaskShape *shape; + MaskObject *maskobj; TransData *td = NULL; TransData2D *td2d = NULL; TransDataMasking *tdm = NULL; /* count */ - shape = mask ? mask->shapes.first : NULL; - while (shape) { - MaskSpline *spline = shape->splines.first; + maskobj = mask ? mask->maskobjs.first : NULL; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { int i; @@ -5970,7 +5970,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } if (t->total == 0) @@ -5985,9 +5985,9 @@ static void createTransMaskingData(bContext *C, TransInfo *t) t->flag |= T_FREE_CUSTOMDATA; /* create data */ - shape = mask->shapes.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + maskobj = mask->maskobjs.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { int i; @@ -6014,7 +6014,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } } diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index dbdde515804..7fb2196e82c 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -43,9 +43,9 @@ typedef struct Mask { ID id; struct AnimData *adt; - ListBase shapes; /* shapes which defines this mask */ - int shapenr; /* index of active shape */ - int tot_shape; /* total number of shapes */ + ListBase maskobjs; /* mask objects */ + int act_maskobj; /* index of active mask object */ + int tot_maskobj; /* total number of mask objects */ } Mask; typedef struct MaskParent { @@ -85,15 +85,15 @@ typedef struct MaskSpline { int weight_interp, pad; /* weight interpolation */ } MaskSpline; -typedef struct MaskShape { - struct MaskShape *next, *prev; +typedef struct MaskObject { + struct MaskObject *next, *prev; - char name[64]; /* name of the shape (64 = MAD_ID_NAME - 2) */ + char name[64]; /* name of the mask object (64 = MAD_ID_NAME - 2) */ - ListBase splines; /* list of splines which defines this shape */ + ListBase splines; /* list of splines which defines this mask object */ struct MaskSpline *act_spline; /* active spline */ struct MaskSplinePoint *act_point; /* active point */ -} MaskShape; +} MaskObject; /* MaskParent->flag */ #define MASK_PARENT_ACTIVE (1 << 0) diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 3d4a5a39dc2..864a7c31cef 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -93,106 +93,106 @@ static void rna_MaskParent_id_type_set(PointerRNA *ptr, int value) mpar->id = NULL; } -static void rna_Mask_shapes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +static void rna_Mask_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Mask *mask = (Mask *)ptr->id.data; - rna_iterator_listbase_begin(iter, &mask->shapes, NULL); + rna_iterator_listbase_begin(iter, &mask->maskobjs, NULL); } -static int rna_Mask_active_shape_index_get(PointerRNA *ptr) +static int rna_Mask_object_active_index_get(PointerRNA *ptr) { Mask *mask = (Mask *)ptr->id.data; - return mask->shapenr; + return mask->act_maskobj; } -static void rna_Mask_active_shape_index_set(PointerRNA *ptr, int value) +static void rna_Mask_object_active_index_set(PointerRNA *ptr, int value) { Mask *mask = (Mask *)ptr->id.data; - mask->shapenr = value; + mask->act_maskobj = value; } -static void rna_Mask_active_shape_index_range(PointerRNA *ptr, int *min, int *max) +static void rna_Mask_object_active_index_range(PointerRNA *ptr, int *min, int *max) { Mask *mask = (Mask *)ptr->id.data; *min = 0; - *max = mask->tot_shape - 1; + *max = mask->tot_maskobj - 1; *max = MAX2(0, *max); } -static PointerRNA rna_Mask_active_shape_get(PointerRNA *ptr) +static PointerRNA rna_Mask_object_active_get(PointerRNA *ptr) { Mask *mask = (Mask *)ptr->id.data; - MaskShape *shape = BKE_mask_shape_active(mask); + MaskObject *maskobj = BKE_mask_object_active(mask); - return rna_pointer_inherit_refine(ptr, &RNA_MaskShape, shape); + return rna_pointer_inherit_refine(ptr, &RNA_MaskObject, maskobj); } -static void rna_Mask_active_shape_set(PointerRNA *ptr, PointerRNA value) +static void rna_Mask_object_active_set(PointerRNA *ptr, PointerRNA value) { Mask *mask = (Mask *)ptr->id.data; - MaskShape *shape = (MaskShape *)value.data; + MaskObject *maskobj = (MaskObject *)value.data; - BKE_mask_shape_active_set(mask, shape); + BKE_mask_object_active_set(mask, maskobj); } -static void rna_MaskShape_splines_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +static void rna_MaskObject_splines_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - MaskShape *shape = (MaskShape *)ptr->data; + MaskObject *maskobj = (MaskObject *)ptr->data; - rna_iterator_listbase_begin(iter, &shape->splines, NULL); + rna_iterator_listbase_begin(iter, &maskobj->splines, NULL); } -void rna_MaskShape_name_set(PointerRNA *ptr, const char *value) +void rna_MaskObject_name_set(PointerRNA *ptr, const char *value) { Mask *mask = (Mask *)ptr->id.data; - MaskShape *shape = (MaskShape *)ptr->data; + MaskObject *maskobj = (MaskObject *)ptr->data; - BLI_strncpy(shape->name, value, sizeof(shape->name)); + BLI_strncpy(maskobj->name, value, sizeof(maskobj->name)); - BKE_mask_shape_unique_name(mask, shape); + BKE_mask_object_unique_name(mask, maskobj); } -static PointerRNA rna_MaskShape_active_spline_get(PointerRNA *ptr) +static PointerRNA rna_MaskObject_active_spline_get(PointerRNA *ptr) { - MaskShape *shape = (MaskShape *)ptr->data; + MaskObject *maskobj = (MaskObject *)ptr->data; - return rna_pointer_inherit_refine(ptr, &RNA_MaskSpline, shape->act_spline); + return rna_pointer_inherit_refine(ptr, &RNA_MaskSpline, maskobj->act_spline); } -static void rna_MaskShape_active_spline_set(PointerRNA *ptr, PointerRNA value) +static void rna_MaskObject_active_spline_set(PointerRNA *ptr, PointerRNA value) { - MaskShape *shape = (MaskShape *)ptr->data; + MaskObject *maskobj = (MaskObject *)ptr->data; MaskSpline *spline = (MaskSpline *)value.data; - int index = BLI_findindex(&shape->splines, spline); + int index = BLI_findindex(&maskobj->splines, spline); if (index >= 0) - shape->act_spline = spline; + maskobj->act_spline = spline; else - shape->act_spline = NULL; + maskobj->act_spline = NULL; } -static PointerRNA rna_MaskShape_active_spline_point_get(PointerRNA *ptr) +static PointerRNA rna_MaskObject_active_spline_point_get(PointerRNA *ptr) { - MaskShape *shape = (MaskShape *)ptr->data; + MaskObject *maskobj = (MaskObject *)ptr->data; - return rna_pointer_inherit_refine(ptr, &RNA_MaskSplinePoint, shape->act_point); + return rna_pointer_inherit_refine(ptr, &RNA_MaskSplinePoint, maskobj->act_point); } -static void rna_MaskShape_active_spline_point_set(PointerRNA *ptr, PointerRNA value) +static void rna_MaskObject_active_spline_point_set(PointerRNA *ptr, PointerRNA value) { - MaskShape *shape = (MaskShape *)ptr->data; - MaskSpline *spline = shape->splines.first; + MaskObject *maskobj = (MaskObject *)ptr->data; + MaskSpline *spline = maskobj->splines.first; MaskSplinePoint *point = (MaskSplinePoint *)value.data; - shape->act_point = NULL; + maskobj->act_point = NULL; while (spline) { if (point >= spline->points && point < spline->points + spline->tot_point) { - shape->act_point = point; + maskobj->act_point = point; break; } @@ -279,29 +279,29 @@ static void rna_MaskSplinePoint_handle_type_set(PointerRNA *ptr, int value) /* ** API ** */ -static MaskShape *rna_Mask_shape_new(Mask *mask, const char *name) +static MaskObject *rna_Mask_object_new(Mask *mask, const char *name) { - MaskShape *shape = BKE_mask_shape_new(mask, name); + MaskObject *maskobj = BKE_mask_object_new(mask, name); WM_main_add_notifier(NC_MASK|NA_EDITED, mask); - return shape; + return maskobj; } -void rna_Mask_shape_remove(Mask *mask, MaskShape *shape) +void rna_Mask_object_remove(Mask *mask, MaskObject *maskobj) { - BKE_mask_shape_remove(mask, shape); + BKE_mask_object_remove(mask, maskobj); WM_main_add_notifier(NC_MASK|NA_EDITED, mask); } -static void rna_MaskShape_spline_add(ID *id, MaskShape *shape, int number) +static void rna_MaskObject_spline_add(ID *id, MaskObject *maskobj, int number) { Mask *mask = (Mask*) id; int i; for (i = 0; i < number; i++) - BKE_mask_spline_add(shape); + BKE_mask_spline_add(maskobj); WM_main_add_notifier(NC_MASK|NA_EDITED, mask); } @@ -402,7 +402,7 @@ static void rna_def_maskSplinePoint(BlenderRNA *brna) rna_def_maskSplinePointUW(brna); srna = RNA_def_struct(brna, "MaskSplinePoint", NULL); - RNA_def_struct_ui_text(srna, "Mask Spline Point", "Single point in spline used for defining mash shape"); + RNA_def_struct_ui_text(srna, "Mask Spline Point", "Single point in spline used for defining mask"); /* Vector values */ prop = RNA_def_property(srna, "handle_left", PROP_FLOAT, PROP_TRANSLATION); @@ -447,34 +447,34 @@ static void rna_def_maskSplinePoint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Feather Points", "Points defining feather"); } -static void rna_def_maskSplines(BlenderRNA *brna) +static void rna_def_mask_splines(BlenderRNA *brna) { StructRNA *srna; FunctionRNA *func; PropertyRNA *prop; srna = RNA_def_struct(brna, "MaskSplines", NULL); - RNA_def_struct_sdna(srna, "MaskShape"); + RNA_def_struct_sdna(srna, "MaskObject"); RNA_def_struct_ui_text(srna, "Mask Splines", "Collection of masking splines"); - func = RNA_def_function(srna, "add", "rna_MaskShape_spline_add"); + func = RNA_def_function(srna, "add", "rna_MaskObject_spline_add"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); - RNA_def_function_ui_description(func, "Add a number of splines to mask shape"); - RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of splines to add to the shape", 0, INT_MAX); + RNA_def_function_ui_description(func, "Add a number of splines to mask object"); + RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of splines to add to the object", 0, INT_MAX); /* active spline */ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "MaskSpline"); - RNA_def_property_pointer_funcs(prop, "rna_MaskShape_active_spline_get", "rna_MaskShape_active_spline_set", NULL, NULL); + RNA_def_property_pointer_funcs(prop, "rna_MaskObject_active_spline_get", "rna_MaskObject_active_spline_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); - RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking shape"); + RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking object"); /* active point */ prop = RNA_def_property(srna, "active_point", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "MaskSplinePoint"); - RNA_def_property_pointer_funcs(prop, "rna_MaskShape_active_spline_point_get", "rna_MaskShape_active_spline_point_set", NULL, NULL); + RNA_def_property_pointer_funcs(prop, "rna_MaskObject_active_spline_point_get", "rna_MaskObject_active_spline_point_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); - RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking shape"); + RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking object"); } static void rna_def_maskSpline(BlenderRNA *brna) @@ -507,34 +507,34 @@ static void rna_def_maskSpline(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Mask_update_data"); } -static void rna_def_maskShape(BlenderRNA *brna) +static void rna_def_mask_object(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; rna_def_maskSpline(brna); - rna_def_maskSplines(brna); + rna_def_mask_splines(brna); - srna = RNA_def_struct(brna, "MaskShape", NULL); - RNA_def_struct_ui_text(srna, "Mask shape", "Single shape used for masking stuff"); + srna = RNA_def_struct(brna, "MaskObject", NULL); + RNA_def_struct_ui_text(srna, "Mask Object", "Single object used for masking pixels"); /* name */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); - RNA_def_property_ui_text(prop, "Name", "Unique name of shape"); - RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MaskShape_name_set"); + RNA_def_property_ui_text(prop, "Name", "Unique name of object"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MaskObject_name_set"); RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2); RNA_def_property_update(prop, 0, "rna_Mask_update_data"); RNA_def_struct_name_property(srna, prop); /* splines */ prop = RNA_def_property(srna, "splines", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_funcs(prop, "rna_MaskShape_splines_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_collection_funcs(prop, "rna_MaskObject_splines_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); RNA_def_property_struct_type(prop, "MaskSpline"); - RNA_def_property_ui_text(prop, "Splines", "Collection of splines which defines this shape"); + RNA_def_property_ui_text(prop, "Splines", "Collection of splines which defines this object"); RNA_def_property_srna(prop, "MaskSplines"); } -static void rna_def_maskShapes(BlenderRNA *brna, PropertyRNA *cprop) +static void rna_def_maskobjects(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; PropertyRNA *prop; @@ -542,27 +542,27 @@ static void rna_def_maskShapes(BlenderRNA *brna, PropertyRNA *cprop) FunctionRNA *func; PropertyRNA *parm; - RNA_def_property_srna(cprop, "MaskShapes"); - srna = RNA_def_struct(brna, "MaskShapes", NULL); + RNA_def_property_srna(cprop, "MaskObjects"); + srna = RNA_def_struct(brna, "MaskObjects", NULL); RNA_def_struct_sdna(srna, "Mask"); - RNA_def_struct_ui_text(srna, "Mask Shapes", "Collection of shapes used by mask"); + RNA_def_struct_ui_text(srna, "Mask Objects", "Collection of objects used by mask"); - func = RNA_def_function(srna, "new", "rna_Mask_shape_new"); - RNA_def_function_ui_description(func, "Add shape to this mask"); - RNA_def_string(func, "name", "", 0, "Name", "Name of new shape"); - parm = RNA_def_pointer(func, "shape", "MaskShape", "", "New mask shape"); + func = RNA_def_function(srna, "new", "rna_Mask_object_new"); + RNA_def_function_ui_description(func, "Add object to this mask"); + RNA_def_string(func, "name", "", 0, "Name", "Name of new object"); + parm = RNA_def_pointer(func, "object", "MaskObject", "", "New mask object"); RNA_def_function_return(func, parm); - func = RNA_def_function(srna, "remove", "rna_Mask_shape_remove"); - RNA_def_function_ui_description(func, "Remove shape from this mask"); - RNA_def_pointer(func, "shape", "MaskShape", "", "Shape to be removed"); + func = RNA_def_function(srna, "remove", "rna_Mask_object_remove"); + RNA_def_function_ui_description(func, "Remove object from this mask"); + RNA_def_pointer(func, "object", "MaskObject", "", "Shape to be removed"); /* active object */ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "MaskShape"); - RNA_def_property_pointer_funcs(prop, "rna_Mask_active_shape_get", "rna_Mask_active_shape_set", NULL, NULL); + RNA_def_property_struct_type(prop, "MaskObject"); + RNA_def_property_pointer_funcs(prop, "rna_Mask_object_active_get", "rna_Mask_object_active_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); - RNA_def_property_ui_text(prop, "Active Shape", "Active shape in this mask"); + RNA_def_property_ui_text(prop, "Active Shape", "Active object in this mask"); } static void rna_def_mask(BlenderRNA *brna) @@ -570,25 +570,25 @@ static void rna_def_mask(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - rna_def_maskShape(brna); + rna_def_mask_object(brna); srna = RNA_def_struct(brna, "Mask", "ID"); RNA_def_struct_ui_text(srna, "Mask", "Mask datablock defining mask for compositing"); RNA_def_struct_ui_icon(srna, ICON_MOD_MASK); - /* shapes */ - prop = RNA_def_property(srna, "shapes", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_funcs(prop, "rna_Mask_shapes_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); - RNA_def_property_struct_type(prop, "MaskShape"); - RNA_def_property_ui_text(prop, "Shapes", "Collection of shapes which defines this mask"); - rna_def_maskShapes(brna, prop); + /* mask objects */ + prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_Mask_objects_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_struct_type(prop, "MaskObject"); + RNA_def_property_ui_text(prop, "Objects", "Collection of objects which defines this mask"); + rna_def_maskobjects(brna, prop); - /* active shape index */ - prop = RNA_def_property(srna, "active_shape_index", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "shapenr"); + /* active maskobj index */ + prop = RNA_def_property(srna, "active_object_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "act_maskobj"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_int_funcs(prop, "rna_Mask_active_shape_index_get", "rna_Mask_active_shape_index_set", "rna_Mask_active_shape_index_range"); - RNA_def_property_ui_text(prop, "Active Shape Index", "Index of active shape in list of all mask's shapes"); + RNA_def_property_int_funcs(prop, "rna_Mask_object_active_index_get", "rna_Mask_object_active_index_set", "rna_Mask_object_active_index_range"); + RNA_def_property_ui_text(prop, "Active Shape Index", "Index of active object in list of all mask's objects"); } void RNA_def_mask(BlenderRNA *brna) diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c index a586824e6e1..2f7f48c5c4b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mask.c +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -58,7 +58,7 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) Mask *mask = (Mask *)node->id; CompBuf *stackbuf; RenderData *rd = data; - MaskShape *shape = mask->shapes.first; + MaskObject *maskobj = mask->maskobjs.first; float *res; int sx, sy; @@ -84,9 +84,9 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE); res = stackbuf->rect; - shape = mask->shapes.first; - while (shape) { - MaskSpline *spline = shape->splines.first; + maskobj = mask->maskobjs.first; + while (maskobj) { + MaskSpline *spline = maskobj->splines.first; while (spline) { float *diff_points; @@ -123,7 +123,7 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) spline = spline->next; } - shape = shape->next; + maskobj = maskobj->next; } /* pass on output and free */ From ec142edaa02038875a329a5272cec8b94bb800bd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 18 May 2012 14:49:30 +0000 Subject: [PATCH 066/183] code cleanup: use for loops for mask/spline looping --- source/blender/blenkernel/intern/mask.c | 12 +- source/blender/blenloader/intern/readfile.c | 10 +- source/blender/blenloader/intern/writefile.c | 10 +- source/blender/editors/mask/mask_draw.c | 12 +- source/blender/editors/mask/mask_ops.c | 104 ++++++------------ .../editors/transform/transform_conversions.c | 10 +- source/blender/makesrna/intern/rna_mask.c | 6 +- .../composite/nodes/node_composite_mask.c | 11 +- 8 files changed, 53 insertions(+), 122 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index e3c2570ab93..1b6dabbf94c 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -957,13 +957,13 @@ void BKE_mask_calc_handles(Mask *mask) void BKE_mask_evaluate(Mask *mask, float ctime) { - MaskObject *maskobj = mask->maskobjs.first; + MaskObject *maskobj; - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; int i; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; BezTriple *bezt = &point->bezt; @@ -977,11 +977,7 @@ void BKE_mask_evaluate(Mask *mask, float ctime) add_v2_v2(bezt->vec[1], delta); add_v2_v2(bezt->vec[2], delta); } - - spline = spline->next; } - - maskobj = maskobj->next; } BKE_mask_calc_handles(mask); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d0b9808697f..17eabc3d7ac 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6282,8 +6282,7 @@ static void direct_link_mask(FileData *fd, Mask *mask) link_list(fd, &mask->maskobjs); - maskobj = mask->maskobjs.first; - while (maskobj) { + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; link_list(fd, &maskobj->splines); @@ -6306,8 +6305,6 @@ static void direct_link_mask(FileData *fd, Mask *mask) maskobj->act_spline = newdataadr(fd, maskobj->act_spline); maskobj->act_point = newdataadr(fd, maskobj->act_point); - - maskobj = maskobj->next; } } @@ -6328,8 +6325,7 @@ static void lib_link_mask(FileData *fd, Main *main) if (mask->adt) lib_link_animdata(fd, &mask->id, mask->adt); - maskobj = mask->maskobjs.first; - while (maskobj) { + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; spline = maskobj->splines.first; @@ -6346,8 +6342,6 @@ static void lib_link_mask(FileData *fd, Main *main) spline = spline->next; } - - maskobj = maskobj->next; } mask->id.flag -= LIB_NEEDLINK; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index a514a3283b1..7a924238c77 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2769,14 +2769,12 @@ static void write_masks(WriteData *wd, ListBase *idbase) if (mask->adt) write_animdata(wd, mask->adt); - maskobj = mask->maskobjs.first; - while (maskobj) { + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; writestruct(wd, DATA, "MaskObject", 1, maskobj); - spline = maskobj->splines.first; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; writestruct(wd, DATA, "MaskSpline", 1, spline); @@ -2788,11 +2786,7 @@ static void write_masks(WriteData *wd, ListBase *idbase) if (point->tot_uw) writestruct(wd, DATA, "MaskSplinePointUW", point->tot_uw, point->uw); } - - spline = spline->next; } - - maskobj = maskobj->next; } } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 06f24c6fa8f..f4022581f2d 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -218,22 +218,18 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline) static void draw_maskobjs(Mask *mask) { - MaskObject *maskobj = mask->maskobjs.first; + MaskObject *maskobj; - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { /* draw curve itself first... */ draw_spline_curve(maskobj, spline); /* ...and then handles over the curve so they're nicely visible */ draw_spline_points(maskobj, spline); - - spline = spline->next; } - - maskobj = maskobj->next; } } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 9b9dbcec7e5..7774af690d7 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -167,19 +167,16 @@ static int points_has_selection(MaskSplinePoint *points, int tot_point) static int mask_has_selection(Mask *mask) { - MaskObject *maskobj = mask->maskobjs.first; + MaskObject *maskobj; - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - while (spline) { - if (points_has_selection(spline->points, spline->tot_point)) + for (spline = maskobj->splines.first; spline; spline = spline->next) { + if (points_has_selection(spline->points, spline->tot_point)) { return TRUE; - - spline = spline->next; + } } - - maskobj = maskobj->next; } return FALSE; @@ -187,7 +184,7 @@ static int mask_has_selection(Mask *mask) static void toggle_selection_all(Mask *mask, int action) { - MaskObject *maskobj = mask->maskobjs.first; + MaskObject *maskobj; if (action == SEL_TOGGLE) { if (mask_has_selection(mask)) @@ -196,10 +193,10 @@ static void toggle_selection_all(Mask *mask, int action) action = SEL_SELECT; } - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -207,11 +204,7 @@ static void toggle_selection_all(Mask *mask, int action) spline_point_select(point, action); } - - spline = spline->next; } - - maskobj = maskobj->next; } } @@ -234,11 +227,10 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - maskobj = mask->maskobjs.first; - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -274,11 +266,7 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal is_handle = FALSE; } } - - spline = spline->next; } - - maskobj = maskobj->next; } if (len < threshold) { @@ -328,11 +316,10 @@ static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - maskobj = mask->maskobjs.first; - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i, tot_feather_point; float *feather_points, *fp; @@ -367,11 +354,7 @@ static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int } MEM_freeN(feather_points); - - spline = spline->next; } - - maskobj = maskobj->next; } if (len < threshold) { @@ -424,11 +407,10 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - maskobj = mask->maskobjs.first; - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -484,11 +466,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], MEM_freeN(diff_points); } } - - spline = spline->next; } - - maskobj = maskobj->next; } if (point && dist < threshold) { @@ -526,11 +504,10 @@ static void mask_flush_selection(Mask *mask) { MaskObject *maskobj; - maskobj = mask->maskobjs.first; - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; spline->flag &= ~SELECT; @@ -552,11 +529,7 @@ static void mask_flush_selection(Mask *mask) } } } - - spline = spline->next; } - - maskobj = maskobj->next; } } @@ -1477,19 +1450,16 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot) static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj = mask->maskobjs.first; + MaskObject *maskobj; - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - while (spline) { - if (points_has_selection(spline->points, spline->tot_point)) + for (spline = maskobj->splines.first; spline; spline = spline->next) { + if (points_has_selection(spline->points, spline->tot_point)) { spline->flag ^= MASK_SPLINE_CYCLIC; - - spline = spline->next; + } } - - maskobj = maskobj->next; } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1553,9 +1523,9 @@ static void delete_feather_points(MaskSplinePoint *point) static int delete_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj = mask->maskobjs.first; + MaskObject *maskobj; - while (maskobj) { + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline = maskobj->splines.first; while (spline) { @@ -1615,8 +1585,6 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) spline = next_spline; } - - maskobj = maskobj->next; } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1645,14 +1613,14 @@ void MASK_OT_delete(wmOperatorType *ot) static int set_handle_type_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj = mask->maskobjs.first; + MaskObject *maskobj; int handle_type = RNA_enum_get(op->ptr, "type"); - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; int i; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; @@ -1662,11 +1630,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) bezt->h1 = bezt->h2 = handle_type; } } - - spline = spline->next; } - - maskobj = maskobj->next; } WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 0a4b7aaeb01..e8cec774a60 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5949,8 +5949,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) TransDataMasking *tdm = NULL; /* count */ - maskobj = mask ? mask->maskobjs.first : NULL; - while (maskobj) { + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline = maskobj->splines.first; while (spline) { @@ -5969,8 +5968,6 @@ static void createTransMaskingData(bContext *C, TransInfo *t) spline = spline->next; } - - maskobj = maskobj->next; } if (t->total == 0) @@ -5985,8 +5982,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) t->flag |= T_FREE_CUSTOMDATA; /* create data */ - maskobj = mask->maskobjs.first; - while (maskobj) { + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline = maskobj->splines.first; while (spline) { @@ -6013,8 +6009,6 @@ static void createTransMaskingData(bContext *C, TransInfo *t) spline = spline->next; } - - maskobj = maskobj->next; } } diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 864a7c31cef..53a6bc34c4a 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -185,19 +185,17 @@ static PointerRNA rna_MaskObject_active_spline_point_get(PointerRNA *ptr) static void rna_MaskObject_active_spline_point_set(PointerRNA *ptr, PointerRNA value) { MaskObject *maskobj = (MaskObject *)ptr->data; - MaskSpline *spline = maskobj->splines.first; + MaskSpline *spline; MaskSplinePoint *point = (MaskSplinePoint *)value.data; maskobj->act_point = NULL; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { if (point >= spline->points && point < spline->points + spline->tot_point) { maskobj->act_point = point; break; } - - spline = spline->next; } } diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c index 2f7f48c5c4b..93d1edd76e8 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mask.c +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -84,11 +84,10 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE); res = stackbuf->rect; - maskobj = mask->maskobjs.first; - while (maskobj) { - MaskSpline *spline = maskobj->splines.first; + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { float *diff_points; int tot_diff_point; @@ -119,11 +118,7 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) MEM_freeN(diff_points); } - - spline = spline->next; } - - maskobj = maskobj->next; } /* pass on output and free */ From e63040a263e2195bf042d599c3db005ca2f15abc Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 18 May 2012 19:17:55 +0000 Subject: [PATCH 067/183] Tomato Branch: * Fix for msvc, it needs stdio header for the NULL keyword. --- intern/raskter/raskter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index f9c2f851f6e..cf8d76372e7 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -28,6 +28,7 @@ * \ingroup RASKTER */ +#include #include #include "raskter.h" From c5dd7879330500365c36f9b4d7af23608a2c3a8b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 18 May 2012 19:22:50 +0000 Subject: [PATCH 068/183] No need to invert brute and normalization flags in rna. Also remove currently unused update callback. --- source/blender/blenkernel/intern/tracking.c | 9 +++++++-- source/blender/makesrna/intern/rna_tracking.c | 19 ++++++------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 2456411c2c2..7ac687e3beb 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1734,8 +1734,13 @@ int BKE_tracking_next(MovieTrackingContext *context) /* Configure the tracker */ options.motion_model = track->motion_model; - options.use_brute = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) == 0); - options.use_normalization = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) == 0); + + options.use_brute = + ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0); + + options.use_normalization = + ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) != 0); + options.num_iterations = 50; options.minimum_correlation = track->minimum_correlation; options.sigma = 0.9; diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 565655ccf37..52cb9f2f409 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -195,13 +195,6 @@ static void rna_trackingTrack_select_set(PointerRNA *ptr, int value) } } -static void rna_tracking_trackerPattern_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; - - BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); -} - static void rna_tracking_trackerSearch_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; @@ -621,14 +614,14 @@ static void rna_def_trackingSettings(BlenderRNA *brna) /* use_brute */ prop = RNA_def_property(srna, "default_use_brute", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); + RNA_def_property_boolean_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); RNA_def_property_ui_text(prop, "Prepass", "Use a brute-force translation-only initialization when tracking"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); /* default use_normalization */ prop = RNA_def_property(srna, "default_use_normalization", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_NORMALIZATION); - RNA_def_property_ui_text(prop, "Normalize", "Normalize light intensities while tracking. Slower."); + RNA_def_property_boolean_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_NORMALIZATION); + RNA_def_property_ui_text(prop, "Normalize", "Normalize light intensities while tracking. Slower"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); /* default minmal correlation */ @@ -932,16 +925,16 @@ static void rna_def_trackingTrack(BlenderRNA *brna) /* use_brute */ prop = RNA_def_property(srna, "use_brute", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); + RNA_def_property_boolean_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Prepass", "Use a brute-force translation only pre-track before refinement"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); /* use_brute */ prop = RNA_def_property(srna, "use_normalization", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_NORMALIZATION); + RNA_def_property_boolean_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_NORMALIZATION); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Normalize", "Normalize light intensities while tracking. Slower."); + RNA_def_property_ui_text(prop, "Normalize", "Normalize light intensities while tracking. Slower"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); /* markers */ From c72298ea19b92ac8674bef8804592d4de8f53a70 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Fri, 18 May 2012 20:04:43 +0000 Subject: [PATCH 069/183] Remove an unnecessary template<> line in libmv. Convert debug logs to LG. --- extern/libmv/libmv/tracking/track_region.cc | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index 6fad3f7af3f..62cc43205d0 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -105,7 +105,6 @@ struct AutoDiff { // Sample the image and gradient when the coordinates are jets, applying the // jacobian appropriately to propagate the derivatives from the coordinates. -template<> template struct AutoDiff > { static ceres::Jet Sample(const FloatImage &image_and_gradient, @@ -353,8 +352,8 @@ class WarpCostFunctor { } *src_mean /= T(num_samples); *dst_mean /= T(num_samples); - std::cout << "Normalization for src:\n" << *src_mean << "\n"; - std::cout << "Normalization for dst:\n" << *dst_mean << "\n"; + LG << "Normalization for src:" << *src_mean; + LG << "Normalization for dst:" << *dst_mean; } // TODO(keir): Consider also computing the cost here. @@ -591,9 +590,9 @@ struct TranslationRotationWarp { Mat2 R = OrthogonalProcrustes(correlation_matrix); parameters[2] = atan2(R(1, 0), R(0, 0)); - std::cout << "correlation_matrix:\n" << correlation_matrix << "\n"; - std::cout << "R:\n" << R << "\n"; - std::cout << "theta:" << parameters[2] << "\n"; + LG << "Correlation_matrix:\n" << correlation_matrix; + LG << "R:\n" << R; + LG << "Theta:" << parameters[2]; } // The strange way of parameterizing the translation and rotation is to make @@ -656,11 +655,12 @@ struct TranslationRotationScaleWarp { correlation_matrix += q1.CornerRelativeToCentroid(i) * q2.CornerRelativeToCentroid(i).transpose(); } - std::cout << "correlation_matrix:\n" << correlation_matrix << "\n"; Mat2 R = OrthogonalProcrustes(correlation_matrix); - std::cout << "R:\n" << R << "\n"; parameters[3] = atan2(R(1, 0), R(0, 0)); - std::cout << "theta:" << parameters[3] << "\n"; + + LG << "Correlation_matrix:\n" << correlation_matrix; + LG << "R:\n" << R; + LG << "Theta:" << parameters[3]; } // The strange way of parameterizing the translation and rotation is to make @@ -741,8 +741,8 @@ struct AffineWarp { parameters[4] = a[2]; parameters[5] = a[3]; - std::cout << "a:" << a.transpose() << "\n"; - std::cout << "t:" << t.transpose() << "\n"; + LG << "a:" << a.transpose(); + LG << "t:" << t.transpose(); } // See comments in other parameterizations about why the centroid is used. From ca446f090bb1347e4855cf941166340d2f024668 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 19 May 2012 16:55:20 +0000 Subject: [PATCH 070/183] Fix aspect ratio correction for translating motion tracking data Still has got some issues when translating masks. --- source/blender/editors/transform/transform.c | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index d06de6be3ae..480edf2d855 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -164,6 +164,7 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) View2D *v2d = t->view; float divx, divy; float mulx, muly; + float aspx = 1.0f, aspy = 1.0f; divx = v2d->mask.xmax-v2d->mask.xmin; divy = v2d->mask.ymax-v2d->mask.ymin; @@ -181,13 +182,16 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) r_vec[1] = muly * (dy) / divy; r_vec[2] = 0.0f; - /* TODO - NOT WORKING, this isnt so bad since its only display aspect */ - if (t->options & CTX_MASK) { - float aspx, aspy; - ED_space_clip_mask_aspect(t->sa->spacedata.first, &aspx, &aspy); - r_vec[0] *= aspx; - r_vec[1] *= aspy; + if (t->options & CTX_MOVIECLIP) { + ED_space_clip_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy); } + else if (t->options & CTX_MASK) { + /* TODO - NOT WORKING, this isnt so bad since its only display aspect */ + ED_space_clip_mask_aspect(t->sa->spacedata.first, &aspx, &aspy); + } + + r_vec[0] *= aspx; + r_vec[1] *= aspy; } else { printf("%s: called in an invalid context\n", __func__); @@ -349,21 +353,17 @@ void removeAspectRatio(TransInfo *t, float vec[2]) else if ((t->spacetype==SPACE_CLIP) && (t->mode==TFM_TRANSLATION)) { if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { SpaceClip *sc = t->sa->spacedata.first; - float aspx, aspy; + float aspx = 1.0f, aspy = 1.0f; if (t->options & CTX_MOVIECLIP) { ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); - - vec[0] *= aspx; - vec[1] *= aspy; } else if (t->options & CTX_MASK) { - ED_space_clip_aspect(sc, &aspx, &aspy); ED_space_clip_mask_aspect(sc, &aspx, &aspy); - - vec[0] *= aspx; - vec[1] *= aspy; } + + vec[0] *= aspx; + vec[1] *= aspy; } } } From 130e7ab6f43a8e358ab7e4d85402f2d6af4b623a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 21 May 2012 09:19:08 +0000 Subject: [PATCH 071/183] Move search area form track to marker structure This allows different markers has different size of search area which makes it possible to scale search area when doing planar tracking. Made changes to all related areas such as transformation, tracking, finally ported marker clamping function, added python bindings for changed search area and added python API for pattern corners. TODO: It's still possible to make marker's center go outside of pattern corners when translating pattern area or rotating it around median point. --- source/blender/blenkernel/BKE_tracking.h | 5 +- source/blender/blenkernel/intern/tracking.c | 140 +++++++----------- source/blender/blenloader/intern/readfile.c | 5 + .../blender/editors/space_clip/clip_buttons.c | 81 +++++----- source/blender/editors/space_clip/clip_draw.c | 28 ++-- .../blender/editors/space_clip/tracking_ops.c | 34 ++--- .../editors/transform/transform_conversions.c | 26 ++-- .../editors/transform/transform_generics.c | 13 +- source/blender/makesdna/DNA_tracking_types.h | 23 ++- source/blender/makesrna/intern/rna_tracking.c | 78 ++++++---- 10 files changed, 218 insertions(+), 215 deletions(-) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 4b94fcb7260..40a023101ba 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -48,7 +48,7 @@ struct Object; struct Scene; void BKE_tracking_init_settings(struct MovieTracking *tracking); -void BKE_tracking_clamp_track(struct MovieTrackingTrack *track, int event); +void BKE_tracking_clamp_marker(struct MovieTrackingMarker *marker, int event); void BKE_tracking_track_flag(struct MovieTrackingTrack *track, int area, int flag, int clear); struct MovieTrackingTrack *BKE_tracking_add_track(struct MovieTracking *tracking, struct ListBase *tracksbase, @@ -76,7 +76,8 @@ struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTra float pos[2], int origin[2]); struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker); -struct ImBuf *BKE_tracking_track_mask_get(struct MovieTracking *tracking, struct MovieTrackingTrack *track, int width, int height); +struct ImBuf *BKE_tracking_track_mask_get(struct MovieTracking *tracking, struct MovieTrackingTrack *track, + struct MovieTrackingMarker *marker, int width, int height); void BKE_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 7ac687e3beb..7df10aa679c 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -104,11 +104,10 @@ static void marker_unified_to_frame_pixel_coordinates(const ImBuf *ibuf, const M unified_to_pixel(ibuf, frame_pixel_coords, frame_pixel_coords); } -static void get_search_origin_frame_pixel(const ImBuf *ibuf, const MovieTrackingTrack *track, - const MovieTrackingMarker *marker, float frame_pixel[2]) +static void get_search_origin_frame_pixel(const ImBuf *ibuf, const MovieTrackingMarker *marker, float frame_pixel[2]) { /* Get the lower left coordinate of the search window and snap to pixel coordinates */ - marker_unified_to_frame_pixel_coordinates(ibuf, marker, track->search_min, frame_pixel); + marker_unified_to_frame_pixel_coordinates(ibuf, marker, marker->search_min, frame_pixel); frame_pixel[0] = (int)frame_pixel[0]; frame_pixel[1] = (int)frame_pixel[1]; } @@ -120,26 +119,24 @@ static void pixel_to_unified(const ImBuf *ibuf, const float pixel_coords[2], flo unified_coords[1] = pixel_coords[1] / ibuf->y; } -static void marker_unified_to_search_pixel(const ImBuf *ibuf, const MovieTrackingTrack *track, - const MovieTrackingMarker *marker, const float marker_unified[2], - float search_pixel[2]) +static void marker_unified_to_search_pixel(const ImBuf *ibuf, const MovieTrackingMarker *marker, + const float marker_unified[2], float search_pixel[2]) { float frame_pixel[2]; float search_origin_frame_pixel[2]; marker_unified_to_frame_pixel_coordinates(ibuf, marker, marker_unified, frame_pixel); - get_search_origin_frame_pixel(ibuf, track, marker, search_origin_frame_pixel); + get_search_origin_frame_pixel(ibuf, marker, search_origin_frame_pixel); sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel); } -static void search_pixel_to_marker_unified(const ImBuf *ibuf, const MovieTrackingTrack *track, - const MovieTrackingMarker *marker, const float search_pixel[2], - float marker_unified[2]) +static void search_pixel_to_marker_unified(const ImBuf *ibuf, const MovieTrackingMarker *marker, + const float search_pixel[2], float marker_unified[2]) { float frame_unified[2]; float search_origin_frame_pixel[2]; - get_search_origin_frame_pixel(ibuf, track, marker, search_origin_frame_pixel); + get_search_origin_frame_pixel(ibuf, marker, search_origin_frame_pixel); add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel); pixel_to_unified(ibuf, frame_unified, frame_unified); @@ -173,34 +170,18 @@ void BKE_tracking_init_settings(MovieTracking *tracking) BKE_tracking_new_object(tracking, "Camera"); } -void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) +void BKE_tracking_clamp_marker(MovieTrackingMarker *marker, int event) { int a; float pat_min[2], pat_max[2]; - float eff_pat_min[2], eff_pat_max[2]; - /* XXX: currently search area is global, pattern size is per-marker, so we'll need to - * find maximal size of pattern to clamp search size nicely - */ - INIT_MINMAX2(pat_min, pat_max); - - for (a = 0; a < track->markersnr; a++) { - float cur_pat_min[2], cur_pat_max[2]; - - BKE_tracking_marker_pattern_minmax(&track->markers[a], cur_pat_min, cur_pat_max); - - DO_MINMAX2(cur_pat_min, pat_min, pat_max); - DO_MINMAX2(cur_pat_max, pat_min, pat_max); - } - - copy_v2_v2(eff_pat_min, pat_min); - copy_v2_v2(eff_pat_max, pat_max); + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); if (event == CLAMP_PAT_DIM) { for (a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ - track->search_min[a] = MIN2(eff_pat_min[a], track->search_min[a]); - track->search_max[a] = MAX2(eff_pat_max[a], track->search_max[a]); + marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); + marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); } } else if (event == CLAMP_PAT_POS) { @@ -208,44 +189,40 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) sub_v2_v2v2(dim, pat_max, pat_min); -#if 0 - /* XXX: needs porting, but we need to know marker here, will be ported after a bit - * more global refactoring - */ for (a = 0; a < 2; a++) { + int b; /* pattern shouldn't be moved outside of search */ - if (eff_pat_min[a] < track->search_min[a]) { - track->pat_min[a] = track->search_min[a] - (eff_pat_min[a] - pat_min[a]); - track->pat_max[a] = track->pat_min[a] + dim[a]; + if (pat_min[a] < marker->search_min[a]) { + for (b = 0; b < 4; b++) + marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a]; } - if (eff_pat_max[a] > track->search_max[a]) { - track->pat_max[a] = track->search_max[a] - (eff_pat_max[a] - pat_max[a]); - track->pat_min[a] = track->pat_max[a] - dim[a]; + if (pat_max[a] > marker->search_max[a]) { + for (b = 0; b < 4; b++) + marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a]; } } -#endif } else if (event == CLAMP_SEARCH_DIM) { for (a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ - track->search_min[a] = MIN2(eff_pat_min[a], track->search_min[a]); - track->search_max[a] = MAX2(eff_pat_max[a], track->search_max[a]); + marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); + marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); } } else if (event == CLAMP_SEARCH_POS) { float dim[2]; - sub_v2_v2v2(dim, track->search_max, track->search_min); + sub_v2_v2v2(dim, marker->search_max, marker->search_min); for (a = 0; a < 2; a++) { /* search shouldn't be moved inside pattern */ - if (track->search_min[a] > eff_pat_min[a]) { - track->search_min[a] = eff_pat_min[a]; - track->search_max[a] = track->search_min[a] + dim[a]; + if (marker->search_min[a] > pat_min[a]) { + marker->search_min[a] = pat_min[a]; + marker->search_max[a] = marker->search_min[a] + dim[a]; } - if (track->search_max[a] < eff_pat_max[a]) { - track->search_max[a] = eff_pat_max[a]; - track->search_min[a] = track->search_max[a] - dim[a]; + if (marker->search_max[a] < pat_max[a]) { + marker->search_max[a] = pat_max[a]; + marker->search_min[a] = marker->search_max[a] - dim[a]; } } } @@ -253,8 +230,8 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) float dim[2]; sub_v2_v2v2(dim, pat_max, pat_min); for (a = 0; a < 2; a++) { - track->search_min[a] = pat_min[a]; - track->search_max[a] = pat_max[a]; + marker->search_min[a] = pat_min[a]; + marker->search_max[a] = pat_max[a]; } } } @@ -324,8 +301,8 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr negate_v2_v2(marker.pattern_corners[2], marker.pattern_corners[0]); negate_v2_v2(marker.pattern_corners[3], marker.pattern_corners[1]); - copy_v2_v2(track->search_max, search); - negate_v2_v2(track->search_min, search); + copy_v2_v2(marker.search_max, search); + negate_v2_v2(marker.search_min, search); BKE_tracking_insert_marker(track, &marker); @@ -1276,13 +1253,13 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov int x, y, w, h; float search_origin[2]; - get_search_origin_frame_pixel(ibuf, track, marker, search_origin); + get_search_origin_frame_pixel(ibuf, marker, search_origin); x = search_origin[0]; y = search_origin[1]; - w = (track->search_max[0] - track->search_min[0]) * ibuf->x; - h = (track->search_max[1] - track->search_min[1]) * ibuf->y; + w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x; + h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); searchibuf->profile = ibuf->profile; @@ -1319,7 +1296,7 @@ static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track) return NULL; } -static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTrackingTrack *track, +static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTrackingMarker *marker, bGPDlayer *layer, ImBuf *ibuf, int width, int height) { bGPDframe *frame = layer->frames.first; @@ -1342,8 +1319,8 @@ static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTra "track mask rasterization points"); for (i = 0; i < stroke->totpoints; i++, fp += 2) { - fp[0] = stroke_points[i].x * width / ibuf->x - track->search_min[0]; - fp[1] = stroke_points[i].y * height * aspy / ibuf->x - track->search_min[1]; + fp[0] = stroke_points[i].x * width / ibuf->x - marker->search_min[0]; + fp[1] = stroke_points[i].y * height * aspy / ibuf->x - marker->search_min[1]; } PLX_raskterize(mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y); @@ -1374,19 +1351,20 @@ static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTra IMB_rect_from_float(ibuf); } -ImBuf *BKE_tracking_track_mask_get(MovieTracking *tracking, MovieTrackingTrack *track, int width, int height) +ImBuf *BKE_tracking_track_mask_get(MovieTracking *tracking, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int width, int height) { ImBuf *ibuf; bGPDlayer *layer = track_mask_gpencil_layer_get(track); int mask_width, mask_height; - mask_width = (track->search_max[0] - track->search_min[0]) * width; - mask_height = (track->search_max[1] - track->search_min[1]) * height; + mask_width = (marker->search_max[0] - marker->search_min[0]) * width; + mask_height = (marker->search_max[1] - marker->search_min[1]) * height; ibuf = IMB_allocImBuf(mask_width, mask_height, 32, IB_rect | IB_rectfloat); if (layer) { - track_mask_gpencil_layer_rasterize(tracking, track, layer, ibuf, width, height); + track_mask_gpencil_layer_rasterize(tracking, marker, layer, ibuf, width, height); } else { float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; @@ -1459,8 +1437,7 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT * This function puts those 5 points into the appropriate frame for tracking * (the "search" coordinate frame). */ -static void get_marker_coords_for_tracking(const ImBuf *ibuf, const MovieTrackingTrack *track, - const MovieTrackingMarker *marker, +static void get_marker_coords_for_tracking(const ImBuf *ibuf, const MovieTrackingMarker *marker, double search_pixel_x[5], double search_pixel_y[5]) { int i; @@ -1469,23 +1446,22 @@ static void get_marker_coords_for_tracking(const ImBuf *ibuf, const MovieTrackin /* Convert the corners into search space coordinates. */ for (i = 0; i < 4; i++) { - marker_unified_to_search_pixel(ibuf, track, marker, marker->pattern_corners[i], pixel_coords); + marker_unified_to_search_pixel(ibuf, marker, marker->pattern_corners[i], pixel_coords); search_pixel_x[i] = pixel_coords[0]; search_pixel_y[i] = pixel_coords[1]; } /* Convert the center position (aka "pos"); this is the origin */ unified_coords[0] = 0.0; unified_coords[1] = 0.0; - marker_unified_to_search_pixel(ibuf, track, marker, unified_coords, pixel_coords); + marker_unified_to_search_pixel(ibuf, marker, unified_coords, pixel_coords); search_pixel_x[4] = pixel_coords[0]; search_pixel_y[4] = pixel_coords[1]; } /* Inverse of above. */ -static void set_marker_coords_from_tracking(const ImBuf *ibuf, const MovieTrackingTrack *track, - MovieTrackingMarker *marker, const double search_pixel_x[5], - const double search_pixel_y[5]) +static void set_marker_coords_from_tracking(const ImBuf *ibuf, MovieTrackingMarker *marker, + const double search_pixel_x[5], const double search_pixel_y[5]) { int i; float marker_unified[2]; @@ -1495,13 +1471,13 @@ static void set_marker_coords_from_tracking(const ImBuf *ibuf, const MovieTracki for (i = 0; i < 4; i++) { search_pixel[0] = search_pixel_x[i]; search_pixel[1] = search_pixel_y[i]; - search_pixel_to_marker_unified(ibuf, track, marker, search_pixel, marker->pattern_corners[i]); + search_pixel_to_marker_unified(ibuf, marker, search_pixel, marker->pattern_corners[i]); } /* Convert the center position (aka "pos"); this is the origin */ search_pixel[0] = search_pixel_x[4]; search_pixel[1] = search_pixel_y[4]; - search_pixel_to_marker_unified(ibuf, track, marker, search_pixel, marker_unified); + search_pixel_to_marker_unified(ibuf, marker, search_pixel, marker_unified); /* If the tracker tracked nothing, then "marker_unified" would be zero. * Otherwise, the entire patch shifted, and that delta should be applied to @@ -1727,9 +1703,10 @@ int BKE_tracking_next(MovieTrackingContext *context) IMB_freeImBuf(reference_ibuf); } - /* XXX: for now, the width & height always match because the - * settings are per-track. This will change soon and in that - * case different sizes must be used */ + /* for now track to the same search area dimension as marker has got for current frame + * will make all tracked markers in currently tracked segment have the same search area + * size, but it's quite close to what is actually needed + */ patch_new = get_search_floatbuf(destination_ibuf, track, marker, &width, &height); /* Configure the tracker */ @@ -1746,11 +1723,8 @@ int BKE_tracking_next(MovieTrackingContext *context) options.sigma = 0.9; /* Convert the marker corners and center into pixel coordinates in the search/destination images. */ - get_marker_coords_for_tracking(destination_ibuf, track, &track_context->marker, - src_pixel_x, src_pixel_y); - - get_marker_coords_for_tracking(destination_ibuf, track, marker, - dst_pixel_x, dst_pixel_y); + get_marker_coords_for_tracking(destination_ibuf, &track_context->marker, src_pixel_x, src_pixel_y); + get_marker_coords_for_tracking(destination_ibuf, marker, dst_pixel_x, dst_pixel_y); /* Run the tracker! */ tracked = libmv_trackRegion(&options, @@ -1765,7 +1739,7 @@ int BKE_tracking_next(MovieTrackingContext *context) if (tracked && !onbound) { memset(&marker_new, 0, sizeof(marker_new)); marker_new = *marker; - set_marker_coords_from_tracking(destination_ibuf, track, &marker_new, dst_pixel_x, dst_pixel_y); + set_marker_coords_from_tracking(destination_ibuf, &marker_new, dst_pixel_x, dst_pixel_y); marker_new.flag |= MARKER_TRACKED; marker_new.framenr = nextfra; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 17465e84a50..3b6b888b7d8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7633,6 +7633,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) marker->pattern_corners[3][0] = track->pat_min[0]; marker->pattern_corners[3][1] = track->pat_max[1]; } + + if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) { + copy_v2_v2(marker->search_min, track->search_min); + copy_v2_v2(marker->search_max, track->search_max); + } } track = track->next; diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 1f5e838f073..5b2c3530aa4 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -190,9 +190,9 @@ typedef struct { int framenr; /* current frame number */ float marker_pos[2]; /* position of marker in pixel coords */ - float track_pat[2]; /* position and dimensions of marker pattern in pixel coords */ + float marker_pat[2]; /* position and dimensions of marker pattern in pixel coords */ float track_offset[2]; /* offset of "parenting" point */ - float track_search_pos[2], track_search[2]; /* position and dimensions of marker search in pixel coords */ + float marker_search_pos[2], marker_search[2]; /* position and dimensions of marker search in pixel coords */ int marker_flag; /* marker's flags */ } MarkerUpdateCb; @@ -240,67 +240,62 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) } else if (event == B_MARKER_PAT_DIM) { float dim[2], pat_dim[2], pat_min[2], pat_max[2]; + float scale_x, scale_y; + int a; BKE_tracking_marker_pattern_minmax(cb->marker, pat_min, pat_max); sub_v2_v2v2(pat_dim, pat_max, pat_min); - dim[0] = cb->track_pat[0] / width; - dim[1] = cb->track_pat[1] / height; + dim[0] = cb->marker_pat[0] / width; + dim[1] = cb->marker_pat[1] / height; - sub_v2_v2(dim, pat_dim); - mul_v2_fl(dim, 0.5f); + scale_x = dim[0] / pat_dim[0]; + scale_y = dim[1] / pat_dim[1]; - cb->marker->pattern_corners[0][0] -= dim[0]; - cb->marker->pattern_corners[0][1] -= dim[1]; + for (a = 0; a < 4; a++) { + cb->marker->pattern_corners[a][0] *= scale_x; + cb->marker->pattern_corners[a][1] *= scale_y; + } - cb->marker->pattern_corners[1][0] += dim[0]; - cb->marker->pattern_corners[1][1] -= dim[1]; - - cb->marker->pattern_corners[2][0] += dim[0]; - cb->marker->pattern_corners[2][1] += dim[1]; - - cb->marker->pattern_corners[3][0] -= dim[0]; - cb->marker->pattern_corners[3][1] += dim[1]; - - BKE_tracking_clamp_track(cb->track, CLAMP_PAT_DIM); + BKE_tracking_clamp_marker(cb->marker, CLAMP_PAT_DIM); ok = TRUE; } else if (event == B_MARKER_SEARCH_POS) { float delta[2], side[2]; - sub_v2_v2v2(side, cb->track->search_max, cb->track->search_min); + sub_v2_v2v2(side, cb->marker->search_max, cb->marker->search_min); mul_v2_fl(side, 0.5f); - delta[0] = cb->track_search_pos[0] / width; - delta[1] = cb->track_search_pos[1] / height; + delta[0] = cb->marker_search_pos[0] / width; + delta[1] = cb->marker_search_pos[1] / height; - sub_v2_v2v2(cb->track->search_min, delta, side); - add_v2_v2v2(cb->track->search_max, delta, side); + sub_v2_v2v2(cb->marker->search_min, delta, side); + add_v2_v2v2(cb->marker->search_max, delta, side); - BKE_tracking_clamp_track(cb->track, CLAMP_SEARCH_POS); + BKE_tracking_clamp_marker(cb->marker, CLAMP_SEARCH_POS); ok = TRUE; } else if (event == B_MARKER_SEARCH_DIM) { float dim[2], search_dim[2]; - sub_v2_v2v2(search_dim, cb->track->search_max, cb->track->search_min); + sub_v2_v2v2(search_dim, cb->marker->search_max, cb->marker->search_min); - dim[0] = cb->track_search[0] / width; - dim[1] = cb->track_search[1] / height; + dim[0] = cb->marker_search[0] / width; + dim[1] = cb->marker_search[1] / height; sub_v2_v2(dim, search_dim); mul_v2_fl(dim, 0.5f); - cb->track->search_min[0] -= dim[0]; - cb->track->search_min[1] -= dim[1]; + cb->marker->search_min[0] -= dim[0]; + cb->marker->search_min[1] -= dim[1]; - cb->track->search_max[0] += dim[0]; - cb->track->search_max[1] += dim[1]; + cb->marker->search_max[0] += dim[0]; + cb->marker->search_max[1] += dim[1]; - BKE_tracking_clamp_track(cb->track, CLAMP_SEARCH_DIM); + BKE_tracking_clamp_marker(cb->marker, CLAMP_SEARCH_DIM); ok = TRUE; } @@ -413,15 +408,15 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); sub_v2_v2v2(pat_dim, pat_max, pat_min); - sub_v2_v2v2(search_dim, track->search_max, track->search_min); + sub_v2_v2v2(search_dim, marker->search_max, marker->search_min); - add_v2_v2v2(search_pos, track->search_max, track->search_min); + add_v2_v2v2(search_pos, marker->search_max, marker->search_min); mul_v2_fl(search_pos, 0.5); to_pixel_space(cb->marker_pos, marker->pos, width, height); - to_pixel_space(cb->track_pat, pat_dim, width, height); - to_pixel_space(cb->track_search, search_dim, width, height); - to_pixel_space(cb->track_search_pos, search_pos, width, height); + to_pixel_space(cb->marker_pat, pat_dim, width, height); + to_pixel_space(cb->marker_search, search_dim, width, height); + to_pixel_space(cb->marker_search_pos, search_pos, width, height); to_pixel_space(cb->track_offset, track->offset, width, height); cb->marker_flag = marker->flag; @@ -457,19 +452,19 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P -10*height, 10.0*height, step, digits, "Y-offset to parenting point"); uiDefBut(block, LABEL, 0, "Pattern Area:", 0, 114, 300, 19, NULL, 0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Width:", 10, 95, 300, 19, &cb->track_pat[0], 3.0f, + uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Width:", 10, 95, 300, 19, &cb->marker_pat[0], 3.0f, 10.0*width, step, digits, "Width of marker's pattern in screen coordinates"); - uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Height:", 10, 76, 300, 19, &cb->track_pat[1], 3.0f, + uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Height:", 10, 76, 300, 19, &cb->marker_pat[1], 3.0f, 10.0*height, step, digits, "Height of marker's pattern in screen coordinates"); uiDefBut(block, LABEL, 0, "Search Area:", 0, 57, 300, 19, NULL, 0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "X:", 10, 38, 145, 19, &cb->track_search_pos[0], + uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "X:", 10, 38, 145, 19, &cb->marker_search_pos[0], -width, width, step, digits, "X-position of search at frame relative to marker's position"); - uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "Y:", 165, 38, 145, 19, &cb->track_search_pos[1], + uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "Y:", 165, 38, 145, 19, &cb->marker_search_pos[1], -height, height, step, digits, "X-position of search at frame relative to marker's position"); - uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Width:", 10, 19, 300, 19, &cb->track_search[0], 3.0f, + uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Width:", 10, 19, 300, 19, &cb->marker_search[0], 3.0f, 10.0*width, step, digits, "Width of marker's search in screen soordinates"); - uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Height:", 10, 0, 300, 19, &cb->track_search[1], 3.0f, + uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Height:", 10, 0, 300, 19, &cb->marker_search[1], 3.0f, 10.0*height, step, digits, "Height of marker's search in screen soordinates"); uiBlockEndAlign(block); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index a06da289326..d654dc9cc77 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -485,10 +485,10 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0); if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) { glBegin(GL_LINE_LOOP); - glVertex2f(track->search_min[0], track->search_min[1]); - glVertex2f(track->search_max[0], track->search_min[1]); - glVertex2f(track->search_max[0], track->search_max[1]); - glVertex2f(track->search_min[0], track->search_max[1]); + glVertex2f(marker->search_min[0], marker->search_min[1]); + glVertex2f(marker->search_max[0], marker->search_min[1]); + glVertex2f(marker->search_max[0], marker->search_max[1]); + glVertex2f(marker->search_min[0], marker->search_max[1]); glEnd(); } glPopMatrix(); @@ -661,10 +661,10 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra } glBegin(GL_LINE_LOOP); - glVertex2f(track->search_min[0], track->search_min[1]); - glVertex2f(track->search_max[0], track->search_min[1]); - glVertex2f(track->search_max[0], track->search_max[1]); - glVertex2f(track->search_min[0], track->search_max[1]); + glVertex2f(marker->search_min[0], marker->search_min[1]); + glVertex2f(marker->search_max[0], marker->search_min[1]); + glVertex2f(marker->search_max[0], marker->search_max[1]); + glVertex2f(marker->search_min[0], marker->search_max[1]); glEnd(); } @@ -761,8 +761,8 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo patdx = MIN2(dx * 2.0f / 3.0f, side / 6.0f); patdy = MIN2(dy * 2.0f / 3.0f, side * width / height / 6.0f); - searchdx = MIN2(dx, (track->search_max[0] - track->search_min[0]) / 6.0f); - searchdy = MIN2(dy, (track->search_max[1] - track->search_min[1]) / 6.0f); + searchdx = MIN2(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f); + searchdy = MIN2(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f); px[0] = 1.0f / sc->zoom / width / sc->scale; px[1] = 1.0f / sc->zoom / height / sc->scale; @@ -776,10 +776,10 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo } /* search offset square */ - draw_marker_slide_square(track->search_min[0], track->search_max[1], searchdx, searchdy, outline, px); + draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px); /* search re-sizing triangle */ - draw_marker_slide_triangle(track->search_max[0], track->search_min[1], searchdx, searchdy, outline, px); + draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px); } if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) { @@ -848,8 +848,8 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) { - dx = track->search_min[0]; - dy = track->search_min[1]; + dx = marker->search_min[0]; + dy = marker->search_min[1]; } else if (sc->flag & SC_SHOW_MARKER_PATTERN) { float pat_min[2], pat_max[2]; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index b072b7475ac..4b37a17f26f 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -310,8 +310,8 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra } } else if (area == TRACK_AREA_SEARCH) { - data->min = track->search_min; - data->max = track->search_max; + data->min = marker->search_min; + data->max = marker->search_max; } if ((area == TRACK_AREA_SEARCH) || @@ -338,7 +338,7 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra return data; } -static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, +static int mouse_on_corner(SpaceClip *sc, MovieTrackingMarker *marker, int area, float co[2], int corner, int width, int height) { int inside = 0; @@ -347,8 +347,8 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki float crn[2], dx, dy, tdx, tdy; if (area == TRACK_AREA_SEARCH) { - copy_v2_v2(min, track->search_min); - copy_v2_v2(max, track->search_max); + copy_v2_v2(min, marker->search_min); + copy_v2_v2(max, marker->search_max); } else { BKE_tracking_marker_pattern_minmax(marker, min, max); @@ -512,11 +512,11 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event) } if (sc->flag & SC_SHOW_MARKER_SEARCH) { - if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 1, width, height)) { + if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 1, width, height)) { customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, 0, SLIDE_ACTION_OFFSET, width, height); } - else if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 0, width, height)) { + else if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 0, width, height)) { customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, 0, SLIDE_ACTION_SIZE, width, height); } @@ -534,12 +534,12 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event) } } else { - if (mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 1, width, height)) { + if (mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 1, width, height)) { customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, 0, SLIDE_ACTION_OFFSET, width, height); } - if (!customdata && mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 0, width, height)) { + if (!customdata && mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 0, width, height)) { customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, 0, SLIDE_ACTION_SIZE, width, height); } @@ -698,9 +698,9 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) } if (data->area == TRACK_AREA_SEARCH) - BKE_tracking_clamp_track(data->track, CLAMP_SEARCH_DIM); + BKE_tracking_clamp_marker(data->marker, CLAMP_SEARCH_DIM); else - BKE_tracking_clamp_track(data->track, CLAMP_PAT_DIM); + BKE_tracking_clamp_marker(data->marker, CLAMP_PAT_DIM); } else if (data->action == SLIDE_ACTION_OFFSET) { float d[2] = {dx, dy}; @@ -719,7 +719,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) } if (data->area == TRACK_AREA_SEARCH) - BKE_tracking_clamp_track(data->track, CLAMP_SEARCH_POS); + BKE_tracking_clamp_marker(data->marker, CLAMP_SEARCH_POS); } else if (data->action == SLIDE_ACTION_POS) { if (data->scale) { @@ -750,7 +750,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) } /* currently only patterns are allowed to have such combination of event and data */ - BKE_tracking_clamp_track(data->track, CLAMP_PAT_DIM); + BKE_tracking_clamp_marker(data->marker, CLAMP_PAT_DIM); } } @@ -846,16 +846,16 @@ static int track_mouse_area(SpaceClip *sc, float co[2], MovieTrackingTrack *trac BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - epsx = MIN4(pat_min[0] - track->search_min[0], track->search_max[0] - pat_max[0], + epsx = MIN4(pat_min[0] - marker->search_min[0], marker->search_max[0] - pat_max[0], fabsf(pat_min[0]), fabsf(pat_max[0])) / 2; - epsy = MIN4(pat_min[1] - track->search_min[1], track->search_max[1] - pat_max[1], + epsy = MIN4(pat_min[1] - marker->search_min[1], marker->search_max[1] - pat_max[1], fabsf(pat_min[1]), fabsf(pat_max[1])) / 2; epsx = MAX2(epsx, 2.0f / width); epsy = MAX2(epsy, 2.0f / height); if (sc->flag & SC_SHOW_MARKER_SEARCH) { - if (mouse_on_rect(co, marker->pos, track->search_min, track->search_max, epsx, epsy)) + if (mouse_on_rect(co, marker->pos, marker->search_min, marker->search_max, epsx, epsy)) return TRACK_AREA_SEARCH; } @@ -929,7 +929,7 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbas /* distance to search boundbox */ if (sc->flag & SC_SHOW_MARKER_SEARCH && TRACK_VIEW_SELECTED(sc, cur)) - d3 = dist_to_rect(co, marker->pos, cur->search_min, cur->search_max); + d3 = dist_to_rect(co, marker->pos, marker->search_min, marker->search_max); /* choose minimal distance. useful for cases of overlapped markers. */ dist = MIN3(d1, d2, d3); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index e8cec774a60..e40a051546d 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5456,7 +5456,7 @@ static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d, MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, sc->user.framenr); tdt->flag = marker->flag; - marker->flag &= ~(MARKER_DISABLED|MARKER_TRACKED); + marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, track->offset, marker->pos, track->offset, aspx, aspy); @@ -5477,10 +5477,10 @@ static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d, if (track->search_flag & SELECT) { markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH, - track->search_min, marker->pos, NULL, aspx, aspy); + marker->search_min, marker->pos, NULL, aspx, aspy); markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH, - track->search_max, marker->pos, NULL, aspx, aspy); + marker->search_max, marker->pos, NULL, aspx, aspy); } } @@ -5556,18 +5556,16 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) td2d++; tdt++; - if ((marker->flag & MARKER_DISABLED) == 0) { - if (track->flag & SELECT) { - td++; - td2d++; - tdt++; - } + if (track->flag & SELECT) { + td++; + td2d++; + tdt++; + } - if (track->pat_flag & SELECT) { - td += 4; - td2d += 4; - tdt += 4; - } + if (track->pat_flag & SELECT) { + td += 4; + td2d += 4; + tdt += 4; } if (track->search_flag & SELECT) { diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index e3ca0957c25..b404c4ef669 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -642,27 +642,30 @@ static void recalcData_spaceclip(TransInfo *t) MovieClip *clip = ED_space_clip(sc); ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; + int framenr = sc->user.framenr; flushTransTracking(t); track = tracksbase->first; while (track) { if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + if (t->mode == TFM_TRANSLATION) { if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_POS); + BKE_tracking_clamp_marker(marker, CLAMP_PAT_POS); if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS); + BKE_tracking_clamp_marker(marker, CLAMP_SEARCH_POS); } else if (t->mode == TFM_RESIZE) { if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); + BKE_tracking_clamp_marker(marker, CLAMP_PAT_DIM); if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); + BKE_tracking_clamp_marker(marker, CLAMP_SEARCH_DIM); } else if (t->mode == TFM_ROTATION) { if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); + BKE_tracking_clamp_marker(marker, CLAMP_PAT_POS); } } diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index a720a14fdcb..c5b0174a3c9 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -81,11 +81,16 @@ typedef struct MovieTrackingMarker { * | | | * | (0) --- (1) * +-------------> X - * - * the coordinates are stored relative to pos. + * + * the coordinates are stored relative to pos. */ float pattern_corners[4][2]; + /* positions of left-bottom and right-top corners of search area (in unified 0..1 units, + * relative to marker->pos + */ + float search_min[2], search_max[2]; + int framenr; /* number of frame marker is associated with */ int flag; /* Marker's flag (alive, ...) */ } MovieTrackingMarker; @@ -97,11 +102,17 @@ typedef struct MovieTrackingTrack { /* ** setings ** */ - /* positions of left-bottom and right-top corners of pattern (in unified 0..1 units, relative to marker->pos) */ - float pat_min[2], pat_max[2] DNA_DEPRECATED; + /* positions of left-bottom and right-top corners of pattern (in unified 0..1 units, + * relative to marker->pos) + * moved to marker's corners since planar tracking implementation + */ + float pat_min[2] DNA_DEPRECATED, pat_max[2] DNA_DEPRECATED; - /* positions of left-bottom and right-top corners of search area (in unified 0..1 units, relative to marker->pos */ - float search_min[2], search_max[2]; + /* positions of left-bottom and right-top corners of search area (in unified 0..1 units, + * relative to marker->pos + * moved to marker since affine tracking implementation + */ + float search_min[2] DNA_DEPRECATED, search_max[2] DNA_DEPRECATED; float offset[2]; /* offset to "parenting" point */ diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 52cb9f2f409..dcbe52c3531 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -195,13 +195,6 @@ static void rna_trackingTrack_select_set(PointerRNA *ptr, int value) } } -static void rna_tracking_trackerSearch_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; - - BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); -} - static char *rna_trackingCamera_path(PointerRNA *UNUSED(ptr)) { return BLI_sprintfN("tracking.camera"); @@ -361,6 +354,20 @@ static void rna_trackingMarker_frame_set(PointerRNA *ptr, int value) } } +static void rna_tracking_markerPattern_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + MovieTrackingMarker *marker = (MovieTrackingMarker *)ptr->data; + + BKE_tracking_clamp_marker(marker, CLAMP_PAT_DIM); +} + +static void rna_tracking_markerSearch_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + MovieTrackingMarker *marker = (MovieTrackingMarker *)ptr->data; + + BKE_tracking_clamp_marker(marker, CLAMP_SEARCH_DIM); +} + /* API */ static void add_tracks_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase, int frame, int number) @@ -467,6 +474,7 @@ static EnumPropertyItem pattern_match_items[] = { {0, NULL, 0, NULL, NULL}}; static int rna_matrix_dimsize_4x4[] = {4, 4}; +static int rna_matrix_dimsize_4x2[] = {4, 2}; static void rna_def_trackingSettings(BlenderRNA *brna) { @@ -797,6 +805,38 @@ static void rna_def_trackingMarker(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MARKER_DISABLED); RNA_def_property_ui_text(prop, "Mode", "Is marker muted for current frame"); RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); + + /* pattern */ + prop = RNA_def_property(srna, "pattern_corners", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "pattern_corners"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x2); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_ui_text(prop, "Pattern Corners", + "Array of coordinates which represents patter's corners in " + " normalized coordinates relative to marker position"); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_markerPattern_update"); + + /* search */ + prop = RNA_def_property(srna, "search_min", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 2); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_float_sdna(prop, NULL, "search_min"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Search Min", + "Left-bottom corner of search area in normalized coordinates relative " + "to marker position"); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_markerSearch_update"); + + prop = RNA_def_property(srna, "search_max", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 2); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_float_sdna(prop, NULL, "search_max"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Search Max", + "Right-bottom corner of search area in normalized coordinates relative " + "to marker position"); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_markerSearch_update"); } static void rna_def_trackingMarkers(BlenderRNA *brna, PropertyRNA *cprop) @@ -857,30 +897,6 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); RNA_def_struct_name_property(srna, prop); - /* Pattern */ - /* XXX The four pattern corners are not exported to rna yet */ - - /* Search */ - prop = RNA_def_property(srna, "search_min", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_array(prop, 2); - RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - RNA_def_property_float_sdna(prop, NULL, "search_min"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Search Min", - "Left-bottom corner of search area in normalized coordinates relative " - "to marker position"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerSearch_update"); - - prop = RNA_def_property(srna, "search_max", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_array(prop, 2); - RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - RNA_def_property_float_sdna(prop, NULL, "search_max"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Search Max", - "Right-bottom corner of search area in normalized coordinates relative " - "to marker position"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerSearch_update"); - /* limit frames */ prop = RNA_def_property(srna, "frames_limit", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); From ebd87e18dfdde9d80bbbe6b74c93535bcad46f8f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 May 2012 11:09:53 +0000 Subject: [PATCH 072/183] mask parenting operator, and clear parenting. (Ctrl+P, Alt+P) - also use offset now with parenting. - draw line from point to parent. --- source/blender/blenkernel/intern/mask.c | 5 +- source/blender/editors/mask/CMakeLists.txt | 1 + source/blender/editors/mask/mask_draw.c | 32 +++ source/blender/editors/mask/mask_editor.c | 8 + source/blender/editors/mask/mask_intern.h | 4 + .../blender/editors/mask/mask_relationships.c | 182 ++++++++++++++++++ 6 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 source/blender/editors/mask/mask_relationships.c diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 1b6dabbf94c..70a83dd5104 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -757,7 +757,7 @@ void BKE_mask_coord_to_movieclip(MovieClip *clip, MovieClipUser *user, float r_c } } -static void evaluate_mask_parent(MaskParent *parent, float ctime, float co[2]) +static void evaluate_mask_parent(MaskParent *parent, float ctime, float r_co[2]) { if (!parent) return; @@ -779,7 +779,8 @@ static void evaluate_mask_parent(MaskParent *parent, float ctime, float co[2]) if (track) { MovieTrackingMarker *marker = BKE_tracking_get_marker(track, ctime); - BKE_mask_coord_from_movieclip(clip, &user, co, marker->pos); + BKE_mask_coord_from_movieclip(clip, &user, r_co, marker->pos); + add_v2_v2(r_co, parent->offset); } } } diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index fc1d2f4be6b..b71b014b628 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRC mask_draw.c mask_editor.c mask_ops.c + mask_relationships.c mask_intern.h ) diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index f4022581f2d..7077450c807 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -62,6 +62,36 @@ static void set_spline_color(MaskObject *maskobj, MaskSpline *spline) } } +static void draw_spline_parents(MaskObject *UNUSED(maskobj), MaskSpline *spline) +{ + int i; + + if (!spline->tot_point) + return; + + glColor3ub(0, 0, 0); + glEnable(GL_LINE_STIPPLE); + glLineStipple(1, 0xAAAA); + + glBegin(GL_LINES); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (point->parent.flag & MASK_PARENT_ACTIVE) { + glVertex2f(point->bezt.vec[1][0], + point->bezt.vec[1][1]); + + glVertex2f(point->bezt.vec[1][0] - point->parent.offset[0], + point->bezt.vec[1][1] - point->parent.offset[1]); + } + } + + glEnd(); + + glDisable(GL_LINE_STIPPLE); +} + /* return non-zero if spline is selected */ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) { @@ -227,6 +257,8 @@ static void draw_maskobjs(Mask *mask) /* draw curve itself first... */ draw_spline_curve(maskobj, spline); + draw_spline_parents(maskobj, spline); + /* ...and then handles over the curve so they're nicely visible */ draw_spline_points(maskobj, spline); } diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index e8311935d86..29c04587539 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -163,6 +163,10 @@ void ED_operatortypes_mask(void) WM_operatortype_append(MASK_OT_slide_point); WM_operatortype_append(MASK_OT_cyclic_toggle); WM_operatortype_append(MASK_OT_handle_type_set); + + /* relationships */ + WM_operatortype_append(MASK_OT_parent_set); + WM_operatortype_append(MASK_OT_parent_clear); } void ED_keymap_mask(wmKeyConfig *keyconf) @@ -196,6 +200,10 @@ void ED_keymap_mask(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MASK_OT_slide_point", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); + /* relationships */ + WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_ALT, 0); + transform_keymap_for_space(keyconf, keymap, SPACE_CLIP); } diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 163239eade7..3ea0f4bce2b 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -56,6 +56,10 @@ void MASK_OT_delete(struct wmOperatorType *ot); void MASK_OT_handle_type_set(struct wmOperatorType *ot); +/* mask_relationships.c */ +void MASK_OT_parent_set(struct wmOperatorType *ot); +void MASK_OT_parent_clear(struct wmOperatorType *ot); + /* mask_editor.c */ int ED_maskediting_poll(struct bContext *C); int ED_maskediting_mask_poll(struct bContext *C); diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c new file mode 100644 index 00000000000..d60a4f9a3ba --- /dev/null +++ b/source/blender/editors/mask/mask_relationships.c @@ -0,0 +1,182 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_ops.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" +#include "BKE_tracking.h" + +#include "DNA_mask_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" /* own include */ + +static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + int i; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL(point)) { + point->parent.flag &= ~MASK_PARENT_ACTIVE; + } + } + } + } + + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; +} + +void MASK_OT_parent_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Parent"; + ot->description = "Clear the masks parenting"; + ot->idname = "MASK_OT_parent_clear"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = mask_parent_clear_exec; + + ot->poll = ED_operator_object_active_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + + /* parent info */ + SpaceClip *sc; + MovieClip *clip; + MovieTrackingTrack *track; + MovieTrackingMarker *marker; + MovieTrackingObject *tracking; + /* done */ + + float parmask_pos[2]; + + if ((NULL == (sc = CTX_wm_space_clip(C))) || + (NULL == (clip = sc->clip)) || + (NULL == (track = clip->tracking.act_track)) || + (NULL == (marker = BKE_tracking_get_marker(track, sc->user.framenr))) || + (NULL == (tracking = BKE_tracking_active_object(&clip->tracking)))) + { + return OPERATOR_CANCELLED; + } + + BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker->pos); + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + int i; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL(point)) { + BezTriple *bezt = &point->bezt; + float tvec[2]; + + point->parent.id_type = ID_MC; + point->parent.id = &clip->id; + strcpy(point->parent.parent, tracking->name); + strcpy(point->parent.sub_parent, track->name); + + point->parent.flag |= MASK_PARENT_ACTIVE; + + sub_v2_v2v2(tvec, parmask_pos, bezt->vec[1]); + + add_v2_v2(bezt->vec[0], tvec); + add_v2_v2(bezt->vec[1], tvec); + add_v2_v2(bezt->vec[2], tvec); + + negate_v2_v2(point->parent.offset, tvec); + } + } + } + } + + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; +} + +/** based on #OBJECT_OT_parent_set */ +void MASK_OT_parent_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Make Parent"; + ot->description = "Set the masks parenting"; + ot->idname = "MASK_OT_parent_set"; + + /* api callbacks */ + //ot->invoke = mask_parent_set_invoke; + ot->exec = mask_parent_set_exec; + + ot->poll = ED_operator_object_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} From 2d613b050b8fe67c3b2f6e7f500f3078001b26ec Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 May 2012 13:42:58 +0000 Subject: [PATCH 073/183] clip/mask parenting from previous commit - clear parent wasnt working - selecting tracks now works when mask editing --- source/blender/editors/mask/mask_editor.c | 8 +++++++- source/blender/editors/mask/mask_ops.c | 4 ++++ source/blender/editors/mask/mask_relationships.c | 1 - source/blender/editors/space_clip/space_clip.c | 8 ++++---- source/blender/editors/space_clip/tracking_ops.c | 3 ++- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index 29c04587539..eaeb0ab9b7f 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -195,6 +195,12 @@ void ED_keymap_mask(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0); RNA_enum_set(kmi->ptr, "action", SEL_INVERT); + /* select clip while in maker view, + * this matches View3D functionality where you can select an + * object while in editmode to allow vertex parenting */ + kmi = WM_keymap_add_item(keymap, "CLIP_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + /* shape */ WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MASK_OT_slide_point", LEFTMOUSE, KM_PRESS, 0, 0); @@ -202,7 +208,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf) /* relationships */ WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "MASK_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0); transform_keymap_for_space(keyconf, keymap, SPACE_CLIP); } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 7774af690d7..d073bd08cef 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1001,6 +1001,8 @@ static int select_exec(bContext *C, wmOperator *op) mask_flush_selection(mask); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; } else { MaskSplinePointUW *uw; @@ -1017,6 +1019,8 @@ static int select_exec(bContext *C, wmOperator *op) mask_flush_selection(mask); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; } } diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index d60a4f9a3ba..07b4508b383 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -91,7 +91,6 @@ void MASK_OT_parent_clear(wmOperatorType *ot) ot->idname = "MASK_OT_parent_clear"; /* api callbacks */ - ot->invoke = WM_menu_invoke; ot->exec = mask_parent_clear_exec; ot->poll = ED_operator_object_active_editable; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 8e92a9198b1..c6d35b03468 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -556,7 +556,7 @@ static void clip_keymap(struct wmKeyConfig *keyconf) /* ******** Hotkeys avalaible for main region only ******** */ keymap = WM_keymap_find(keyconf, "Clip Editor", SPACE_CLIP, 0); - +// keymap->poll = ED_space_clip_tracking_poll; /* ** View/navigation ** */ WM_keymap_add_item(keymap, "CLIP_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0); @@ -1048,14 +1048,14 @@ static void clip_main_area_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); /* own keymap */ + keymap= WM_keymap_find(wm->defaultconf, "Mask Editor", 0, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap = WM_keymap_find(wm->defaultconf, "Clip", SPACE_CLIP, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); keymap = WM_keymap_find(wm->defaultconf, "Clip Editor", SPACE_CLIP, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - - keymap= WM_keymap_find(wm->defaultconf, "Mask Editor", 0, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } static void clip_main_area_draw(const bContext *C, ARegion *ar) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 4b37a17f26f..6d34994e081 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1039,7 +1039,8 @@ void CLIP_OT_select(wmOperatorType *ot) /* api callbacks */ ot->exec = select_exec; ot->invoke = select_invoke; - ot->poll = ED_space_clip_tracking_poll; + //ot->poll = ED_space_clip_tracking_poll; // so mask view can Ctrl+RMB markers + ot->poll = ED_space_clip_view_clip_poll; /* flags */ ot->flag = OPTYPE_UNDO; From 857444d7beeb91a9d2aaee9530fd778b4cd274f7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 22 May 2012 10:48:29 +0000 Subject: [PATCH 074/183] move select operations into their own file --- source/blender/editors/mask/CMakeLists.txt | 1 + source/blender/editors/mask/mask_intern.h | 24 +- source/blender/editors/mask/mask_ops.c | 286 ++-------------- .../blender/editors/mask/mask_relationships.c | 2 +- source/blender/editors/mask/mask_select.c | 304 ++++++++++++++++++ 5 files changed, 346 insertions(+), 271 deletions(-) create mode 100644 source/blender/editors/mask/mask_select.c diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index b71b014b628..55c31e35536 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRC mask_editor.c mask_ops.c mask_relationships.c + mask_select.c mask_intern.h ) diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 3ea0f4bce2b..623ef5fd533 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -47,19 +47,37 @@ void MASK_OT_add_vertex(struct wmOperatorType *ot); void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); void MASK_OT_cyclic_toggle(struct wmOperatorType *ot); -void MASK_OT_select(struct wmOperatorType *ot); -void MASK_OT_select_all(struct wmOperatorType *ot); - void MASK_OT_slide_point(struct wmOperatorType *ot); void MASK_OT_delete(struct wmOperatorType *ot); void MASK_OT_handle_type_set(struct wmOperatorType *ot); +int ED_mask_feather_find_nearest( + struct bContext *C, struct Mask *mask, float normal_co[2], int threshold, + struct MaskObject **maskobj_r, struct MaskSpline **spline_r, struct MaskSplinePoint **point_r, + struct MaskSplinePointUW **uw_r, float *score); + +struct MaskSplinePoint *ED_mask_point_find_nearest( + struct bContext *C, struct Mask *mask, float normal_co[2], int threshold, + struct MaskObject **maskobj_r, struct MaskSpline **spline_r, int *is_handle_r, + float *score); + /* mask_relationships.c */ void MASK_OT_parent_set(struct wmOperatorType *ot); void MASK_OT_parent_clear(struct wmOperatorType *ot); +/* mask_select.c */ +void MASK_OT_select(struct wmOperatorType *ot); +void MASK_OT_select_all(struct wmOperatorType *ot); + +int ED_mask_spline_select_check(struct MaskSplinePoint *points, int tot_point); +int ED_mask_select_check(struct Mask *mask); +void ED_mask_point_select(struct MaskSplinePoint *point, int action); + +void ED_mask_select_toggle_all(struct Mask *mask, int action); +void ED_mask_select_flush_all(struct Mask *mask); + /* mask_editor.c */ int ED_maskediting_poll(struct bContext *C); int ED_maskediting_mask_poll(struct bContext *C); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index d073bd08cef..4054814604e 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -57,38 +57,6 @@ /******************** utility functions *********************/ -static void spline_point_select(MaskSplinePoint *point, int action) -{ - int i; - - switch (action) { - case SEL_SELECT: - MASKPOINT_SEL(point); - break; - case SEL_DESELECT: - MASKPOINT_DESEL(point); - break; - case SEL_INVERT: - MASKPOINT_INVSEL(point); - break; - } - - for (i = 0; i < point->tot_uw; i++) { - switch (action) { - case SEL_SELECT: - point->uw[i].flag |= SELECT; - break; - case SEL_DESELECT: - point->uw[i].flag &= ~SELECT; - break; - case SEL_INVERT: - point->uw[i].flag ^= SELECT; - break; - } - } -} - - static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, float start_u, const float co[2]) { const float proj_eps = 1e-3; @@ -151,66 +119,9 @@ static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, fl return u; } -static int points_has_selection(MaskSplinePoint *points, int tot_point) -{ - int i; - - for (i = 0; i < tot_point; i++) { - MaskSplinePoint *point = &points[i]; - - if (MASKPOINT_ISSEL(point)) - return TRUE; - } - - return FALSE; -} - -static int mask_has_selection(Mask *mask) -{ - MaskObject *maskobj; - - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline; - - for (spline = maskobj->splines.first; spline; spline = spline->next) { - if (points_has_selection(spline->points, spline->tot_point)) { - return TRUE; - } - } - } - - return FALSE; -} - -static void toggle_selection_all(Mask *mask, int action) -{ - MaskObject *maskobj; - - if (action == SEL_TOGGLE) { - if (mask_has_selection(mask)) - action = SEL_DESELECT; - else - action = SEL_SELECT; - } - - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline; - - for (spline = maskobj->splines.first; spline; spline = spline->next) { - int i; - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - - spline_point_select(point, action); - } - } - } -} - -static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal_co[2], int threshold, - MaskObject **maskobj_r, MaskSpline **spline_r, int *is_handle_r, - float *score) +MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float normal_co[2], int threshold, + MaskObject **maskobj_r, MaskSpline **spline_r, int *is_handle_r, + float *score) { MaskObject *maskobj; MaskObject *point_maskobj = NULL; @@ -297,9 +208,9 @@ static MaskSplinePoint *find_nearest_point(bContext *C, Mask *mask, float normal return NULL; } -static int find_nearest_feather(bContext *C, Mask *mask, float normal_co[2], int threshold, - MaskObject **maskobj_r, MaskSpline **spline_r, MaskSplinePoint **point_r, - MaskSplinePointUW **uw_r, float *score) +int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], int threshold, + MaskObject **maskobj_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + MaskSplinePointUW **uw_r, float *score) { MaskObject *maskobj, *point_maskobj = NULL; MaskSpline *point_spline = NULL; @@ -500,39 +411,6 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], return FALSE; } -static void mask_flush_selection(Mask *mask) -{ - MaskObject *maskobj; - - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline; - - for (spline = maskobj->splines.first; spline; spline = spline->next) { - int i; - - spline->flag &= ~SELECT; - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *cur_point = &spline->points[i]; - - if (MASKPOINT_ISSEL(cur_point)) { - spline->flag |= SELECT; - } - else { - int j; - - for (j = 0; j < cur_point->tot_uw; j++) { - if (cur_point->uw[j].flag & SELECT) { - spline->flag |= SELECT; - break; - } - } - } - } - } - } -} - /******************** create new mask *********************/ static int mask_new_exec(bContext *C, wmOperator *op) @@ -677,9 +555,9 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) ED_mask_mouse_pos(C, event, co); ED_mask_size(C, &width, &height); - cv_point = find_nearest_point(C, mask, co, threshold, &cv_maskobj, &cv_spline, &is_handle, &cv_score); + cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_maskobj, &cv_spline, &is_handle, &cv_score); - if (find_nearest_feather(C, mask, co, threshold, &feather_maskobj, &feather_spline, &feather_point, &uw, &feather_score)) { + if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_maskobj, &feather_spline, &feather_point, &uw, &feather_score)) { if (slide_feather || !cv_point || feather_score < cv_score) { action = SLIDE_ACTION_FEATHER; @@ -756,19 +634,19 @@ static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) if (slidedata->uw) { if ((slidedata->uw->flag & SELECT) == 0) { - toggle_selection_all(mask, SEL_DESELECT); + ED_mask_select_toggle_all(mask, SEL_DESELECT); slidedata->uw->flag |= SELECT; - mask_flush_selection(mask); + ED_mask_select_flush_all(mask); } } else if (!MASKPOINT_ISSEL(slidedata->point)) { - toggle_selection_all(mask, SEL_DESELECT); + ED_mask_select_toggle_all(mask, SEL_DESELECT); - spline_point_select(slidedata->point, SEL_SELECT); + ED_mask_point_select(slidedata->point, SEL_SELECT); - mask_flush_selection(mask); + ED_mask_select_flush_all(mask); } slidedata->maskobj->act_spline = slidedata->spline; @@ -934,132 +812,6 @@ void MASK_OT_slide_point(wmOperatorType *ot) RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide slide feather instead of vertex"); } -/******************** toggle selection *********************/ - -static int select_all_exec(bContext *C, wmOperator *op) -{ - Mask *mask = CTX_data_edit_mask(C); - int action = RNA_enum_get(op->ptr, "action"); - - toggle_selection_all(mask, action); - mask_flush_selection(mask); - - WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); - - return OPERATOR_FINISHED; -} - -void MASK_OT_select_all(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select or Deselect All"; - ot->description = "Change selection of all curve points"; - ot->idname = "MASK_OT_select_all"; - - /* api callbacks */ - ot->exec = select_all_exec; - ot->poll = ED_maskediting_mask_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_select_all(ot); -} - -/******************** select *********************/ - -static int select_exec(bContext *C, wmOperator *op) -{ - Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; - MaskSpline *spline; - MaskSplinePoint *point = NULL; - float co[2]; - int extend = RNA_boolean_get(op->ptr, "extend"); - int is_handle = 0; - const float threshold = 19; - - RNA_float_get_array(op->ptr, "location", co); - - point = find_nearest_point(C, mask, co, threshold, &maskobj, &spline, &is_handle, NULL); - - if (point) { - if (!extend) - toggle_selection_all(mask, SEL_DESELECT); - - if (is_handle) { - MASKPOINT_HANDLE_SEL(point); - } - else { - spline_point_select(point, SEL_SELECT); - } - - maskobj->act_spline = spline; - maskobj->act_point = point; - - mask_flush_selection(mask); - - WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); - - return OPERATOR_FINISHED; - } - else { - MaskSplinePointUW *uw; - - if (find_nearest_feather(C, mask, co, threshold, &maskobj, &spline, &point, &uw, NULL)) { - if (!extend) - toggle_selection_all(mask, SEL_DESELECT); - - uw->flag |= SELECT; - - maskobj->act_spline = spline; - maskobj->act_point = point; - - mask_flush_selection(mask); - - WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); - - return OPERATOR_FINISHED; - } - } - - return OPERATOR_PASS_THROUGH; -} - -static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - float co[2]; - - ED_mask_mouse_pos(C, event, co); - - RNA_float_set_array(op->ptr, "location", co); - - return select_exec(C, op); -} - -void MASK_OT_select(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select"; - ot->description = "Select spline points"; - ot->idname = "MASK_OT_select"; - - /* api callbacks */ - ot->exec = select_exec; - ot->invoke = select_invoke; - ot->poll = ED_maskediting_mask_poll; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "extend", 0, - "Extend", "Extend selection rather than clearing the existing selection"); - RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, - "Location", "Location of vertex in normalized space", -1.0f, 1.0f); -} - /******************** add vertex *********************/ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, @@ -1187,7 +939,7 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask /* select new point */ MASKPOINT_SEL(new_point); - mask_flush_selection(mask); + ED_mask_select_flush_all(mask); } /* **** add subdivide vertex **** */ @@ -1204,7 +956,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) MaskSplinePoint *new_point_array, *new_point; int point_index = point - spline->points; - toggle_selection_all(mask, SEL_DESELECT); + ED_mask_select_toggle_all(mask, SEL_DESELECT); new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); @@ -1280,7 +1032,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) MaskSplinePoint *point; MaskSplinePoint *new_point = NULL, *ref_point = NULL; - toggle_selection_all(mask, SEL_DESELECT); + ED_mask_select_toggle_all(mask, SEL_DESELECT); maskobj = BKE_mask_object_active(mask); @@ -1401,7 +1153,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "location", co); - point = find_nearest_point(C, mask, co, threshold, NULL, NULL, NULL, NULL); + point = ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL); if (point) return OPERATOR_FINISHED; @@ -1460,7 +1212,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) MaskSpline *spline; for (spline = maskobj->splines.first; spline; spline = spline->next) { - if (points_has_selection(spline->points, spline->tot_point)) { + if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { spline->flag ^= MASK_SPLINE_CYCLIC; } } @@ -1584,7 +1336,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) spline->points = new_points; spline->tot_point = j; - mask_flush_selection(mask); + ED_mask_select_flush_all(mask); } spline = next_spline; diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 07b4508b383..136376336d8 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/editors/mask/mask_ops.c +/** \file blender/editors/mask/mask_relationshops.c * \ingroup edmask */ diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c new file mode 100644 index 00000000000..672ea96778c --- /dev/null +++ b/source/blender/editors/mask/mask_select.c @@ -0,0 +1,304 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_select.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" /* own include */ + +int ED_mask_spline_select_check(MaskSplinePoint *points, int tot_point) +{ + int i; + + for (i = 0; i < tot_point; i++) { + MaskSplinePoint *point = &points[i]; + + if (MASKPOINT_ISSEL(point)) + return TRUE; + } + + return FALSE; +} + +int ED_mask_select_check(Mask *mask) +{ + MaskObject *maskobj; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { + return TRUE; + } + } + } + + return FALSE; +} + +void ED_mask_point_select(MaskSplinePoint *point, int action) +{ + int i; + + switch (action) { + case SEL_SELECT: + MASKPOINT_SEL(point); + break; + case SEL_DESELECT: + MASKPOINT_DESEL(point); + break; + case SEL_INVERT: + MASKPOINT_INVSEL(point); + break; + } + + for (i = 0; i < point->tot_uw; i++) { + switch (action) { + case SEL_SELECT: + point->uw[i].flag |= SELECT; + break; + case SEL_DESELECT: + point->uw[i].flag &= ~SELECT; + break; + case SEL_INVERT: + point->uw[i].flag ^= SELECT; + break; + } + } +} + + +void ED_mask_select_toggle_all(Mask *mask, int action) +{ + MaskObject *maskobj; + + if (action == SEL_TOGGLE) { + if (ED_mask_select_check(mask)) + action = SEL_DESELECT; + else + action = SEL_SELECT; + } + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + ED_mask_point_select(point, action); + } + } + } +} + +void ED_mask_select_flush_all(Mask *mask) +{ + MaskObject *maskobj; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + int i; + + spline->flag &= ~SELECT; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *cur_point = &spline->points[i]; + + if (MASKPOINT_ISSEL(cur_point)) { + spline->flag |= SELECT; + } + else { + int j; + + for (j = 0; j < cur_point->tot_uw; j++) { + if (cur_point->uw[j].flag & SELECT) { + spline->flag |= SELECT; + break; + } + } + } + } + } + } +} + +/******************** toggle selection *********************/ + +static int select_all_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + int action = RNA_enum_get(op->ptr, "action"); + + ED_mask_select_toggle_all(mask, action); + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_select_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select or Deselect All"; + ot->description = "Change selection of all curve points"; + ot->idname = "MASK_OT_select_all"; + + /* api callbacks */ + ot->exec = select_all_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_select_all(ot); +} + +/******************** select *********************/ + +static int select_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + float co[2]; + int extend = RNA_boolean_get(op->ptr, "extend"); + int is_handle = 0; + const float threshold = 19; + + RNA_float_get_array(op->ptr, "location", co); + + point = ED_mask_point_find_nearest(C, mask, co, threshold, &maskobj, &spline, &is_handle, NULL); + + if (point) { + if (!extend) + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + if (is_handle) { + MASKPOINT_HANDLE_SEL(point); + } + else { + ED_mask_point_select(point, SEL_SELECT); + } + + maskobj->act_spline = spline; + maskobj->act_point = point; + + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + else { + MaskSplinePointUW *uw; + + if (ED_mask_feather_find_nearest(C, mask, co, threshold, &maskobj, &spline, &point, &uw, NULL)) { + if (!extend) + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + uw->flag |= SELECT; + + maskobj->act_spline = spline; + maskobj->act_point = point; + + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + } + + return OPERATOR_PASS_THROUGH; +} + +static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + float co[2]; + + ED_mask_mouse_pos(C, event, co); + + RNA_float_set_array(op->ptr, "location", co); + + return select_exec(C, op); +} + +void MASK_OT_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select"; + ot->description = "Select spline points"; + ot->idname = "MASK_OT_select"; + + /* api callbacks */ + ot->exec = select_exec; + ot->invoke = select_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "extend", 0, + "Extend", "Extend selection rather than clearing the existing selection"); + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); +} From e76812a1d7490b01066c0f751d5311b58825ffd8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 23 May 2012 12:15:12 +0000 Subject: [PATCH 075/183] fix for crash selecting curve pointsx --- source/blender/editors/mask/mask_select.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 672ea96778c..f1ee620e2ce 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -254,7 +254,8 @@ static int select_exec(bContext *C, wmOperator *op) if (!extend) ED_mask_select_toggle_all(mask, SEL_DESELECT); - uw->flag |= SELECT; + if (uw) + uw->flag |= SELECT; maskobj->act_spline = spline; maskobj->act_point = point; From 3e1df2d12ebb319c0d12d2511d1a728667b5e45e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 May 2012 13:31:36 +0000 Subject: [PATCH 076/183] shapekeys for masks - this doesnt use existing shapekey code however. --- source/blender/blenkernel/BKE_mask.h | 21 +- source/blender/blenkernel/intern/mask.c | 275 ++++++++++++++++++- source/blender/blenkernel/intern/scene.c | 4 +- source/blender/blenloader/intern/readfile.c | 10 +- source/blender/blenloader/intern/writefile.c | 6 + source/blender/editors/mask/CMakeLists.txt | 1 + source/blender/editors/mask/mask_editor.c | 8 + source/blender/editors/mask/mask_intern.h | 4 + source/blender/editors/mask/mask_shapekey.c | 130 +++++++++ source/blender/makesdna/DNA_mask_types.h | 13 + 10 files changed, 459 insertions(+), 13 deletions(-) create mode 100755 source/blender/editors/mask/mask_shapekey.c diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 361de2c38ce..e09aa9d8355 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -31,6 +31,7 @@ struct Main; struct Mask; struct MaskParent; struct MaskObject; +struct MaskObjectShape; struct MaskSpline; struct MaskSplinePoint; struct MaskSplinePointUW; @@ -83,8 +84,8 @@ void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *u /* parenting */ -void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime); -void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene); +void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_newframe); +void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe); void BKE_mask_parent_init(struct MaskParent *parent); void BKE_mask_calc_handle_adjacent_length(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); void BKE_mask_calc_handle_point(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); @@ -93,6 +94,22 @@ void BKE_mask_get_handle_point_adjacent(struct Mask *mask, struct MaskSpline *sp struct MaskSplinePoint **r_point_prev, struct MaskSplinePoint **r_point_next); void BKE_mask_calc_handles(struct Mask *mask); +/* animation */ +int BKE_mask_object_shape_totvert(struct MaskObject *maskobj); +void BKE_mask_object_shape_from_mask(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape); +void BKE_mask_object_shape_to_mask(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape); +void BKE_mask_object_shape_to_mask_interp(struct MaskObject *maskobj, + struct MaskObjectShape *maskobj_shape_a, + struct MaskObjectShape *maskobj_shape_b, + const float fac); +struct MaskObjectShape *BKE_mask_object_shape_find_frame(struct MaskObject *maskobj, int frame); +int BKE_mask_object_shape_find_frame_range(struct MaskObject *maskobj, int frame, + struct MaskObjectShape **r_maskobj_shape_a, + struct MaskObjectShape **r_maskobj_shape_b); +struct MaskObjectShape *BKE_mask_object_shape_varify_frame(struct MaskObject *maskobj, int frame); +void BKE_mask_object_shape_unlink(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape); +void BKE_mask_object_shape_sort(struct MaskObject *maskobj); + #define MASKPOINT_ISSEL(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) #define MASKPOINT_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 #define MASKPOINT_DESEL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 70a83dd5104..56bf90499e5 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -662,10 +662,20 @@ void BKE_mask_spline_free(MaskSpline *spline) MEM_freeN(spline); } +void BKE_mask_object_shape_free(MaskObjectShape *maskobj_shape) +{ + MEM_freeN(maskobj_shape->data); + + MEM_freeN(maskobj_shape); +} + void BKE_mask_object_free(MaskObject *maskobj) { - MaskSpline *spline = maskobj->splines.first; + MaskSpline *spline; + MaskObjectShape *maskobj_shape; + /* free splines */ + spline = maskobj->splines.first; while (spline) { MaskSpline *next_spline = spline->next; @@ -675,6 +685,17 @@ void BKE_mask_object_free(MaskObject *maskobj) spline = next_spline; } + /* free animation data */ + maskobj_shape = maskobj->splines_shapes.first; + while (maskobj_shape) { + MaskObjectShape *next_maskobj_shape = maskobj_shape->next; + + BLI_remlink(&maskobj->splines_shapes, maskobj_shape); + BKE_mask_object_shape_free(maskobj_shape); + + maskobj_shape = next_maskobj_shape; + } + MEM_freeN(maskobj); } @@ -956,7 +977,7 @@ void BKE_mask_calc_handles(Mask *mask) } } -void BKE_mask_evaluate(Mask *mask, float ctime) +void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) { MaskObject *maskobj; @@ -964,6 +985,40 @@ void BKE_mask_evaluate(Mask *mask, float ctime) MaskSpline *spline; int i; + /* animation if available */ + if (do_newframe) { + MaskObjectShape *maskobj_shape_a; + MaskObjectShape *maskobj_shape_b; + int found; + + if ((found = BKE_mask_object_shape_find_frame_range(maskobj, (int)ctime, + &maskobj_shape_a, &maskobj_shape_b))) + { + if (found == 1) { +#if 0 + printf("%s: exact %d %d (%d)\n", __func__, (int)ctime, BLI_countlist(&maskobj->splines_shapes), + maskobj_shape_a->frame); +#endif + + BKE_mask_object_shape_to_mask(maskobj, maskobj_shape_a); + } + else if (found == 2) { + float w = maskobj_shape_b->frame - maskobj_shape_a->frame; +#if 0 + printf("%s: tween %d %d (%d %d)\n", __func__, (int)ctime, BLI_countlist(&maskobj->splines_shapes), + maskobj_shape_a->frame, maskobj_shape_b->frame); +#endif + BKE_mask_object_shape_to_mask_interp(maskobj, maskobj_shape_a, maskobj_shape_b, + (ctime - maskobj_shape_a->frame) / w); + } + else { + /* always fail, should never happen */ + BLI_assert(found == 2); + } + } + } + /* animation done... */ + for (spline = maskobj->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; @@ -984,22 +1039,22 @@ void BKE_mask_evaluate(Mask *mask, float ctime) BKE_mask_calc_handles(mask); } -void BKE_mask_evaluate_all_masks(Main *bmain, float ctime) +void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const int do_newframe) { Mask *mask; for (mask = bmain->mask.first; mask; mask = mask->id.next) { - BKE_mask_evaluate(mask, ctime); + BKE_mask_evaluate(mask, ctime, do_newframe); } } -void BKE_mask_update_scene(Main *bmain, Scene *scene) +void BKE_mask_update_scene(Main *bmain, Scene *scene, const int do_newframe) { Mask *mask; for (mask = bmain->mask.first; mask; mask = mask->id.next) { if (mask->id.flag & LIB_ID_RECALC) { - BKE_mask_evaluate_all_masks(bmain, CFRA); + BKE_mask_evaluate_all_masks(bmain, CFRA, do_newframe); } } } @@ -1008,3 +1063,211 @@ void BKE_mask_parent_init(MaskParent *parent) { parent->id_type = ID_MC; } + + +/* *** own animation/shapekey implimentation *** + * BKE_mask_object_shape_XXX */ + +int BKE_mask_object_shape_totvert(MaskObject *maskobj) +{ + int tot = 0; + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + tot += spline->tot_point; + } + + return tot; +} + +/* these functions match. copy is swapped */ +void BKE_mask_object_shape_from_mask(MaskObject *maskobj, MaskObjectShape *maskobj_shape) +{ + int tot = BKE_mask_object_shape_totvert(maskobj); + + if (maskobj_shape->tot_vert == tot) { + float *fp = maskobj_shape->data; + + MaskSpline *spline; + for (spline = maskobj->splines.first; spline; spline = spline->next) { + int i; + for (i = 0; i < spline->tot_point; i++) { + BezTriple *bezt = &spline->points[i].bezt; + /* *** BKE_mask_object_shape_to_mask - swapped *** */ + copy_v2_v2(fp, bezt->vec[0]); fp += 2; + copy_v2_v2(fp, bezt->vec[1]); fp += 2; + copy_v2_v2(fp, bezt->vec[2]); fp += 2; + fp[0] = bezt->weight; + fp[1] = bezt->radius; fp += 2; + } + } + } + else { + printf("%s: vert mismatch %d != %d\n", __func__, maskobj_shape->tot_vert, tot); + } +} + +void BKE_mask_object_shape_to_mask(MaskObject *maskobj, MaskObjectShape *maskobj_shape) +{ + int tot = BKE_mask_object_shape_totvert(maskobj); + + if (maskobj_shape->tot_vert == tot) { + float *fp = maskobj_shape->data; + + MaskSpline *spline; + for (spline = maskobj->splines.first; spline; spline = spline->next) { + int i; + for (i = 0; i < spline->tot_point; i++) { + BezTriple *bezt = &spline->points[i].bezt; + /* *** BKE_mask_object_shape_from_mask - swapped *** */ + copy_v2_v2(bezt->vec[0], fp); fp += 2; + copy_v2_v2(bezt->vec[1], fp); fp += 2; + copy_v2_v2(bezt->vec[2], fp); fp += 2; + bezt->weight = fp[0]; + bezt->radius = fp[1]; fp += 2; + } + } + } + else { + printf("%s: vert mismatch %d != %d\n", __func__, maskobj_shape->tot_vert, tot); + } +} + +BLI_INLINE void interp_v2_v2v2_flfl(float target[2], const float a[2], const float b[2], + const float t, const float s) +{ + target[0] = s * a[0] + t * b[0]; + target[1] = s * a[1] + t * b[1]; +} + +/* linear interpolation only */ +void BKE_mask_object_shape_to_mask_interp(MaskObject *maskobj, + MaskObjectShape *maskobj_shape_a, + MaskObjectShape *maskobj_shape_b, + const float fac) +{ + int tot = BKE_mask_object_shape_totvert(maskobj); + printf("%.6f\n", fac); + if (maskobj_shape_a->tot_vert == tot && maskobj_shape_b->tot_vert == tot) { + float *fp_a = maskobj_shape_a->data; + float *fp_b = maskobj_shape_b->data; + const float ifac = 1.0f - fac; + + MaskSpline *spline; + for (spline = maskobj->splines.first; spline; spline = spline->next) { + int i; + for (i = 0; i < spline->tot_point; i++) { + BezTriple *bezt = &spline->points[i].bezt; + /* *** BKE_mask_object_shape_from_mask - swapped *** */ + interp_v2_v2v2_flfl(bezt->vec[0], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2; + interp_v2_v2v2_flfl(bezt->vec[1], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2; + interp_v2_v2v2_flfl(bezt->vec[2], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2; + bezt->weight = (fp_a[0] * ifac) + (fp_b[0] * fac); + bezt->radius = (fp_a[1] * ifac) + (fp_b[1] * fac); fp_a += 2; fp_b += 2; + } + } + } + else { + printf("%s: vert mismatch %d != %d != %d\n", + __func__, maskobj_shape_a->tot_vert, maskobj_shape_b->tot_vert, tot); + } +} + +MaskObjectShape *BKE_mask_object_shape_find_frame(MaskObject *maskobj, int frame) +{ + MaskObjectShape *maskobj_shape; + + for (maskobj_shape = maskobj->splines_shapes.first; + maskobj_shape; + maskobj_shape = maskobj_shape->next) + { + if (frame == maskobj_shape->frame) { + return maskobj_shape; + } + else if (frame > maskobj_shape->frame) { + break; + } + } + + return NULL; +} + +/* when returning 2 - the frame isnt found but before/after frames are */ +int BKE_mask_object_shape_find_frame_range(MaskObject *maskobj, int frame, + MaskObjectShape **r_maskobj_shape_a, + MaskObjectShape **r_maskobj_shape_b) +{ + MaskObjectShape *maskobj_shape; + + for (maskobj_shape = maskobj->splines_shapes.first; + maskobj_shape; + maskobj_shape = maskobj_shape->next) + { + if (frame == maskobj_shape->frame) { + *r_maskobj_shape_a = maskobj_shape; + *r_maskobj_shape_b = NULL; + return 1; + } + else if (frame < maskobj_shape->frame) { + if (maskobj_shape->prev) { + *r_maskobj_shape_a = maskobj_shape->prev; + *r_maskobj_shape_b = maskobj_shape; + return 2; + } + else { + *r_maskobj_shape_a = maskobj_shape; + *r_maskobj_shape_b = NULL; + return 1; + } + } + } + + *r_maskobj_shape_a = NULL; + *r_maskobj_shape_b = NULL; + + return 0; +} + +MaskObjectShape *BKE_mask_object_shape_varify_frame(MaskObject *maskobj, int frame) +{ + MaskObjectShape *maskobj_shape; + + maskobj_shape = BKE_mask_object_shape_find_frame(maskobj, frame); + + if (maskobj_shape == NULL) { + int tot_vert = BKE_mask_object_shape_totvert(maskobj); + + maskobj_shape = MEM_mallocN(sizeof(MaskObjectShape), __func__); + maskobj_shape->frame = frame; + maskobj_shape->tot_vert = tot_vert; + maskobj_shape->data = MEM_mallocN(tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + + BLI_addtail(&maskobj->splines_shapes, maskobj_shape); + + BKE_mask_object_shape_sort(maskobj); + } + + return maskobj_shape; +} + +void BKE_mask_object_shape_unlink(MaskObject *maskobj, MaskObjectShape *maskobj_shape) +{ + BLI_remlink(&maskobj->splines_shapes, maskobj_shape); + + BKE_mask_object_shape_free(maskobj_shape); +} + +static int mask_object_shape_sort_cb(void *maskobj_shape_a_ptr, void *maskobj_shape_b_ptr) +{ + MaskObjectShape *maskobj_shape_a = (MaskObjectShape *)maskobj_shape_a_ptr; + MaskObjectShape *maskobj_shape_b = (MaskObjectShape *)maskobj_shape_b_ptr; + + if (maskobj_shape_a->frame < maskobj_shape_b->frame) return -1; + else if (maskobj_shape_a->frame > maskobj_shape_b->frame) return 1; + else return 0; +} + +void BKE_mask_object_shape_sort(MaskObject *maskobj) +{ + BLI_sortlist(&maskobj->splines_shapes, mask_object_shape_sort_cb); +} diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index ee791ff0a0a..752203a5453 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1004,7 +1004,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen sound_update_scene(scene); /* update masking curves */ - BKE_mask_update_scene(bmain, scene); + BKE_mask_update_scene(bmain, scene, FALSE); } /* this is called in main loop, doing tagged updates before redraw */ @@ -1075,7 +1075,7 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) * so don't call within 'scene_update_tagged_recursive' */ DAG_scene_update_flags(bmain, sce, lay, TRUE); // only stuff that moves or needs display still - BKE_mask_evaluate_all_masks(bmain, ctime); + BKE_mask_evaluate_all_masks(bmain, ctime, TRUE); /* All 'standard' (i.e. without any dependencies) animation is handled here, * with an 'local' to 'macro' order of evaluation. This should ensure that diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index edea4ccab5b..4ea7da44f11 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6197,11 +6197,11 @@ static void direct_link_mask(FileData *fd, Mask *mask) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; + MaskObjectShape *maskobj_shape; link_list(fd, &maskobj->splines); - spline = maskobj->splines.first; - while (spline) { + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; spline->points = newdataadr(fd, spline->points); @@ -6212,8 +6212,12 @@ static void direct_link_mask(FileData *fd, Mask *mask) if (point->tot_uw) point->uw = newdataadr(fd, point->uw); } + } - spline = spline->next; + link_list(fd, &maskobj->splines_shapes); + + for (maskobj_shape = maskobj->splines_shapes.first; maskobj_shape; maskobj_shape = maskobj_shape->next) { + maskobj_shape->data = newdataadr(fd, maskobj_shape->data); } maskobj->act_spline = newdataadr(fd, maskobj->act_spline); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 29cfd7f7f5c..7c9945ef517 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2771,6 +2771,7 @@ static void write_masks(WriteData *wd, ListBase *idbase) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; + MaskObjectShape *maskobj_shape; writestruct(wd, DATA, "MaskObject", 1, maskobj); @@ -2787,6 +2788,11 @@ static void write_masks(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, "MaskSplinePointUW", point->tot_uw, point->uw); } } + + for (maskobj_shape = maskobj->splines_shapes.first; maskobj_shape; maskobj_shape = maskobj_shape->next) { + writestruct(wd, DATA, "MaskObjectShape", 1, maskobj_shape); + writedata(wd, DATA, maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, maskobj_shape->data); + } } } diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index 55c31e35536..e6f26e32c06 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -42,6 +42,7 @@ set(SRC mask_ops.c mask_relationships.c mask_select.c + mask_shapekey.c mask_intern.h ) diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index eaeb0ab9b7f..749c2c0237e 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -167,6 +167,10 @@ void ED_operatortypes_mask(void) /* relationships */ WM_operatortype_append(MASK_OT_parent_set); WM_operatortype_append(MASK_OT_parent_clear); + + /* shapekeys */ + WM_operatortype_append(MASK_OT_shape_key_insert); + WM_operatortype_append(MASK_OT_shape_key_clear); } void ED_keymap_mask(wmKeyConfig *keyconf) @@ -210,6 +214,10 @@ void ED_keymap_mask(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MASK_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "MASK_OT_shape_key_insert", IKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_shape_key_clear", IKEY, KM_PRESS, KM_ALT, 0); + + transform_keymap_for_space(keyconf, keymap, SPACE_CLIP); } diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 623ef5fd533..fee4b63529d 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -88,4 +88,8 @@ void ED_mask_aspect(struct bContext *C, float *aspx, float *aspy); void ED_mask_pixelspace_factor(struct bContext *C, float *scalex, float *scaley); void ED_mask_mouse_pos(struct bContext *C, struct wmEvent *event, float co[2]); +/* mask_shapekey.c */ +void MASK_OT_shape_key_insert(struct wmOperatorType *ot); +void MASK_OT_shape_key_clear(struct wmOperatorType *ot); + #endif /* __MASK_INTERN_H__ */ diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c new file mode 100755 index 00000000000..80ba605fe72 --- /dev/null +++ b/source/blender/editors/mask/mask_shapekey.c @@ -0,0 +1,130 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_shapekey.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "DNA_mask_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" /* own include */ + +static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + const int frame = CFRA; + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskObjectShape *maskobj_shape; + + maskobj_shape = BKE_mask_object_shape_varify_frame(maskobj, frame); + BKE_mask_object_shape_from_mask(maskobj, maskobj_shape); + } + + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; +} + +void MASK_OT_shape_key_insert(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Insert Shape Key"; + ot->description = ""; + ot->idname = "MASK_OT_shape_key_insert"; + + /* api callbacks */ + ot->exec = mask_shape_key_insert_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + const int frame = CFRA; + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskObjectShape *maskobj_shape; + + maskobj_shape = BKE_mask_object_shape_find_frame(maskobj, frame); + + if (maskobj_shape) { + BKE_mask_object_shape_unlink(maskobj, maskobj_shape); + } + } + + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; +} + +void MASK_OT_shape_key_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Shape Key"; + ot->description = ""; + ot->idname = "MASK_OT_shape_key_clear"; + + /* api callbacks */ + ot->exec = mask_shape_key_clear_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 7fb2196e82c..9f163adc77b 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -85,12 +85,23 @@ typedef struct MaskSpline { int weight_interp, pad; /* weight interpolation */ } MaskSpline; +/* one per frame */ +typedef struct MaskObjectShape { + struct MaskObjectShape *next, *prev; + + float *data; /* u coordinate along spline segment and weight of this point */ + int tot_vert; /* to ensure no buffer overruns's: alloc size is (tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE) */ + int frame; /* different flags of this point */ +} MaskObjectShape; + typedef struct MaskObject { struct MaskObject *next, *prev; char name[64]; /* name of the mask object (64 = MAD_ID_NAME - 2) */ ListBase splines; /* list of splines which defines this mask object */ + ListBase splines_shapes; + struct MaskSpline *act_spline; /* active spline */ struct MaskSplinePoint *act_point; /* active point */ } MaskObject; @@ -105,4 +116,6 @@ typedef struct MaskObject { #define MASK_SPLINE_INTERP_LINEAR 1 #define MASK_SPLINE_INTERP_EASE 2 +#define MASK_OBJECT_SHAPE_ELEM_SIZE 8 /* 3x 2D points + weight + radius == 8 */ + #endif // __DNA_MASK_TYPES_H__ From 3305674bb5615b959bc5dfa73dab7e9783849081 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 24 May 2012 14:01:00 +0000 Subject: [PATCH 077/183] Port mask node to new compositor system Works in the same way as double edge node -- not actually multithreaded but currently it's fast enough to be used in such way. In the future it might be changed in some way. Move actual mask rasterization code to BKE so it's resued by old compositor system and new compositor. Also in the future it might be used to display mask preview in mask editor. --- source/blender/blenkernel/BKE_mask.h | 3 + source/blender/blenkernel/intern/mask.c | 45 +++++++ source/blender/compositor/CMakeLists.txt | 5 + .../compositor/intern/COM_Converter.cpp | 4 + .../blender/compositor/nodes/COM_MaskNode.cpp | 65 +++++++++++ .../blender/compositor/nodes/COM_MaskNode.h | 38 ++++++ .../operations/COM_MaskOperation.cpp | 110 ++++++++++++++++++ .../compositor/operations/COM_MaskOperation.h | 66 +++++++++++ source/blender/nodes/CMakeLists.txt | 1 - .../composite/nodes/node_composite_mask.c | 40 +------ 10 files changed, 337 insertions(+), 40 deletions(-) create mode 100644 source/blender/compositor/nodes/COM_MaskNode.cpp create mode 100644 source/blender/compositor/nodes/COM_MaskNode.h create mode 100644 source/blender/compositor/operations/COM_MaskOperation.cpp create mode 100644 source/blender/compositor/operations/COM_MaskOperation.h diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index e09aa9d8355..21be180b05f 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -110,6 +110,9 @@ struct MaskObjectShape *BKE_mask_object_shape_varify_frame(struct MaskObject *ma void BKE_mask_object_shape_unlink(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape); void BKE_mask_object_shape_sort(struct MaskObject *maskobj); +/* rasterization */ +void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer); + #define MASKPOINT_ISSEL(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) #define MASKPOINT_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 #define MASKPOINT_DESEL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 56bf90499e5..ea2acc4dbd3 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -55,6 +55,8 @@ #include "BKE_movieclip.h" #include "BKE_utildefines.h" +#include "raskter.h" + /* mask objects */ MaskObject *BKE_mask_object_new(Mask *mask, const char *name) @@ -1271,3 +1273,46 @@ void BKE_mask_object_shape_sort(MaskObject *maskobj) { BLI_sortlist(&maskobj->splines_shapes, mask_object_shape_sort_cb); } + +/* rasterization */ +void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) +{ + MaskObject *maskobj; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + float *diff_points; + int tot_diff_point; + + diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); + + /* TODO, make this optional! */ + if (width != height) { + float *fp; + int i; + float asp; + + if (width < height) { + fp = &diff_points[0]; + asp = (float)width / (float)height; + } + else { + fp = &diff_points[1]; + asp = (float)height / (float)width; + } + + for (i = 0; i < tot_diff_point; i++, fp += 2) { + (*fp) = (((*fp) - 0.5f) / asp) + 0.5f; + } + } + + if (tot_diff_point) { + PLX_raskterize(diff_points, tot_diff_point, buffer, width, height); + + MEM_freeN(diff_points); + } + } + } +} diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 3230c0ec33d..5e778d4d03b 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -134,6 +134,8 @@ set(SRC nodes/COM_MovieClipNode.h nodes/COM_OutputFileNode.cpp nodes/COM_OutputFileNode.h + nodes/COM_MaskNode.cpp + nodes/COM_MaskNode.h # output nodes nodes/COM_CompositorNode.cpp @@ -603,6 +605,9 @@ operations/COM_ConvertDepthToRadiusOperation.cpp operations/COM_AntiAliasOperation.cpp operations/COM_AntiAliasOperation.h + + operations/COM_MaskOperation.cpp + operations/COM_MaskOperation.h ) blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 3cb297801ca..dc6409e7b86 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -111,6 +111,7 @@ #include "COM_DefocusNode.h" #include "COM_DoubleEdgeMaskNode.h" #include "COM_CropNode.h" +#include "COM_MaskNode.h" Node *Converter::convert(bNode *bNode) { @@ -347,6 +348,9 @@ case CMP_NODE_OUTPUT_FILE: case CMP_NODE_CROP: node = new CropNode(bNode); break; + case CMP_NODE_MASK: + node = new MaskNode(bNode); + break; /* not inplemented yet */ default: node = new MuteNode(bNode); diff --git a/source/blender/compositor/nodes/COM_MaskNode.cpp b/source/blender/compositor/nodes/COM_MaskNode.cpp new file mode 100644 index 00000000000..991c3f75e05 --- /dev/null +++ b/source/blender/compositor/nodes/COM_MaskNode.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_MaskNode.h" +#include "COM_ExecutionSystem.h" +#include "COM_MaskOperation.h" + +extern "C" { + #include "DNA_mask_types.h" +} + +MaskNode::MaskNode(bNode *editorNode): Node(editorNode) +{ +} + +void MaskNode::convertToOperations(ExecutionSystem *graph, CompositorContext * context) +{ + const RenderData *data = &context->getScene()->r; + + InputSocket *inputImage = this->getInputSocket(0); + OutputSocket *outputMask = this->getOutputSocket(0); + + bNode *editorNode = this->getbNode(); + Mask *mask = (Mask *)editorNode->id; + + // always connect the output image + MaskOperation *operation = new MaskOperation(); + + if (inputImage->isConnected()) { + inputImage->relinkConnections(operation->getInputSocket(0), 0, graph); + } + else { + operation->setMaskWidth(data->xsch * data->size / 100.0f); + operation->setMaskHeight(data->ysch * data->size / 100.0f); + } + + if (outputMask->isConnected()) { + outputMask->relinkConnections(operation->getOutputSocket()); + } + + operation->setMask(mask); + operation->setFramenumber(context->getFramenumber()); + + graph->addOperation(operation); +} diff --git a/source/blender/compositor/nodes/COM_MaskNode.h b/source/blender/compositor/nodes/COM_MaskNode.h new file mode 100644 index 00000000000..9d2ea1889d9 --- /dev/null +++ b/source/blender/compositor/nodes/COM_MaskNode.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_Node.h" +#include "DNA_node_types.h" + +/** + * @brief MaskNode + * @ingroup Node + */ +class MaskNode : public Node { + + +public: + MaskNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); + +}; diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp new file mode 100644 index 00000000000..7c71e884e5c --- /dev/null +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -0,0 +1,110 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_MaskOperation.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "DNA_scene_types.h" + +extern "C" { + #include "BKE_mask.h" +} + +MaskOperation::MaskOperation(): NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->mask = NULL; + this->maskWidth = 0; + this->maskHeight = 0; + this->framenumber = 0; + this->rasterizedMask = NULL; + setComplex(true); +} + +void MaskOperation::initExecution() +{ + initMutex(); + this->rasterizedMask = NULL; +} + +void MaskOperation::deinitExecution() +{ + if (this->rasterizedMask) { + MEM_freeN(rasterizedMask); + this->rasterizedMask = NULL; + } +} + +void *MaskOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) +{ + if (this->rasterizedMask) + return this->rasterizedMask; + + BLI_mutex_lock(getMutex()); + if (this->rasterizedMask == NULL) { + int width = this->getWidth(); + int height = this->getHeight(); + + this->rasterizedMask = (float *)MEM_callocN(sizeof(float) * width * height, "rasterized mask"); + BKE_mask_rasterize(mask, width, height, this->rasterizedMask); + } + BLI_mutex_unlock(getMutex()); + + return this->rasterizedMask; +} + +void MaskOperation::determineResolution(unsigned int resolution[], unsigned int preferredResolution[]) +{ + if (maskWidth == 0 || maskHeight == 0) { + NodeOperation::determineResolution(resolution, preferredResolution); + } + else { + unsigned int nr[2]; + + nr[0] = maskWidth; + nr[1] = maskHeight; + + NodeOperation::determineResolution(resolution, nr); + + resolution[0] = maskWidth; + resolution[1] = maskHeight; + } +} + +void MaskOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) +{ + float *buffer = (float*) data; + int index = (y * this->getWidth() + x); + + color[0] = buffer[index]; + color[1] = buffer[index]; + color[2] = buffer[index]; + color[3] = 1.0f; +} + + diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h new file mode 100644 index 00000000000..9f2c7f53f56 --- /dev/null +++ b/source/blender/compositor/operations/COM_MaskOperation.h @@ -0,0 +1,66 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + + +#ifndef _COM_MaskOperation_h +#define _COM_MaskOperation_h + +#include "COM_NodeOperation.h" +#include "DNA_scene_types.h" +#include "DNA_mask_types.h" +#include "BLI_listbase.h" +#include "IMB_imbuf_types.h" + +/** + * Class with implementation of mask rasterization + */ +class MaskOperation : public NodeOperation { +protected: + Mask *mask; + int maskWidth; + int maskHeight; + int framenumber; + float *rasterizedMask; + + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[], unsigned int preferredResolution[]); + +public: + MaskOperation(); + + void initExecution(); + void deinitExecution(); + + void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); + + void setMask(Mask *mask) {this->mask = mask;} + void setMaskWidth(int width) {this->maskWidth = width;} + void setMaskHeight(int height) {this->maskHeight = height;} + void setFramenumber(int framenumber) {this->framenumber = framenumber;} + + void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data); +}; + +#endif diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 358abb08ba4..5e36f90f217 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -35,7 +35,6 @@ set(INC ../makesrna ../render/extern/include ../../../intern/guardedalloc - ../../../intern/raskter ../compositor ) diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c index 93d1edd76e8..c90c7918660 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mask.c +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -36,8 +36,6 @@ #include "BKE_mask.h" -// XXX: ... -#include "../../../../intern/raskter/raskter.h" #include "node_composite_util.h" /* **************** Translate ******************** */ @@ -58,7 +56,6 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) Mask *mask = (Mask *)node->id; CompBuf *stackbuf; RenderData *rd = data; - MaskObject *maskobj = mask->maskobjs.first; float *res; int sx, sy; @@ -84,42 +81,7 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE); res = stackbuf->rect; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline; - - for (spline = maskobj->splines.first; spline; spline = spline->next) { - float *diff_points; - int tot_diff_point; - - diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); - - /* TODO, make this optional! */ - if (sx != sy) { - float *fp; - int i; - float asp; - - if (sx < sy) { - fp = &diff_points[0]; - asp = (float)sx / (float)sy; - } - else { - fp = &diff_points[1]; - asp = (float)sy / (float)sx; - } - - for (i = 0; i < tot_diff_point; i++, fp += 2) { - (*fp) = (((*fp) - 0.5f) / asp) + 0.5f; - } - } - - if (tot_diff_point) { - PLX_raskterize(diff_points, tot_diff_point, res, sx, sy); - - MEM_freeN(diff_points); - } - } - } + BKE_mask_rasterize(mask, sx, sy, res); /* pass on output and free */ out[0]->data = stackbuf; From a8a855ecd7be7a695a67308f20c07332bce768db Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 May 2012 14:06:10 +0000 Subject: [PATCH 078/183] fix for incorrect range function args. --- source/blender/makesrna/intern/rna_mask.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 53a6bc34c4a..1345011cd7e 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -114,13 +114,16 @@ static void rna_Mask_object_active_index_set(PointerRNA *ptr, int value) mask->act_maskobj = value; } -static void rna_Mask_object_active_index_range(PointerRNA *ptr, int *min, int *max) +static void rna_Mask_object_active_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { Mask *mask = (Mask *)ptr->id.data; *min = 0; *max = mask->tot_maskobj - 1; *max = MAX2(0, *max); + + *softmin = *min; + *softmax = *max; } static PointerRNA rna_Mask_object_active_get(PointerRNA *ptr) From ebd39522d89a6f5d1b5ae58342cb1a3b28ebd714 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 May 2012 15:29:50 +0000 Subject: [PATCH 079/183] fix bug in own recent edits - shape key insertion --- source/blender/blenkernel/intern/mask.c | 15 +++++++++++- source/blender/editors/mask/mask_shapekey.c | 26 ++++++++++++++++----- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index ea2acc4dbd3..5e9d659c68a 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1186,7 +1186,7 @@ MaskObjectShape *BKE_mask_object_shape_find_frame(MaskObject *maskobj, int frame if (frame == maskobj_shape->frame) { return maskobj_shape; } - else if (frame > maskobj_shape->frame) { + else if (frame < maskobj_shape->frame) { break; } } @@ -1249,6 +1249,19 @@ MaskObjectShape *BKE_mask_object_shape_varify_frame(MaskObject *maskobj, int fra BKE_mask_object_shape_sort(maskobj); } +#if 0 + { + MaskObjectShape *maskobj_shape; + int i = 0; + for (maskobj_shape = maskobj->splines_shapes.first; + maskobj_shape; + maskobj_shape = maskobj_shape->next) + { + printf("mask %d, %d\n", i++, maskobj_shape->frame); + } + } +#endif + return maskobj_shape; } diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 80ba605fe72..c80ca979077 100755 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -62,18 +62,25 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op)) const int frame = CFRA; Mask *mask = CTX_data_edit_mask(C); MaskObject *maskobj; + int change = FALSE; for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskObjectShape *maskobj_shape; maskobj_shape = BKE_mask_object_shape_varify_frame(maskobj, frame); BKE_mask_object_shape_from_mask(maskobj, maskobj_shape); + change = TRUE; } - WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, 0); + if (change) { + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void MASK_OT_shape_key_insert(wmOperatorType *ot) @@ -97,6 +104,7 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) const int frame = CFRA; Mask *mask = CTX_data_edit_mask(C); MaskObject *maskobj; + int change = FALSE; for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskObjectShape *maskobj_shape; @@ -105,13 +113,19 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) if (maskobj_shape) { BKE_mask_object_shape_unlink(maskobj, maskobj_shape); + change = TRUE; } } - WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, 0); + if (change) { + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void MASK_OT_shape_key_clear(wmOperatorType *ot) From afe2def93cbeb164c4c0a6b97d97b580936b9429 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 May 2012 19:16:08 +0000 Subject: [PATCH 080/183] adding new keyframes now updates existing shapekeys --- source/blender/blenkernel/BKE_mask.h | 5 + source/blender/blenkernel/intern/mask.c | 126 +++++++++++++++++++++--- source/blender/editors/mask/mask_ops.c | 17 ++++ 3 files changed, 134 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 21be180b05f..7745eb0b972 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -110,6 +110,11 @@ struct MaskObjectShape *BKE_mask_object_shape_varify_frame(struct MaskObject *ma void BKE_mask_object_shape_unlink(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape); void BKE_mask_object_shape_sort(struct MaskObject *maskobj); +int BKE_mask_object_shape_spline_index(struct MaskObject *maskobj, int index, + struct MaskSpline **r_maskobj_shape, int *r_index); +void BKE_mask_object_shape_changed_add(struct MaskObject *maskobj, int index, + int do_init, int do_init_interpolate); + /* rasterization */ void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 5e9d659c68a..c09947ef540 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1082,6 +1082,24 @@ int BKE_mask_object_shape_totvert(MaskObject *maskobj) return tot; } +static void mask_object_shape_from_mask_point(BezTriple *bezt, float fp[MASK_OBJECT_SHAPE_ELEM_SIZE]) +{ + copy_v2_v2(&fp[0], bezt->vec[0]); + copy_v2_v2(&fp[2], bezt->vec[1]); + copy_v2_v2(&fp[4], bezt->vec[2]); + fp[6] = bezt->weight; + fp[7] = bezt->radius; +} + +static void mask_object_shape_to_mask_point(BezTriple *bezt, float fp[MASK_OBJECT_SHAPE_ELEM_SIZE]) +{ + copy_v2_v2(bezt->vec[0], &fp[0]); + copy_v2_v2(bezt->vec[1], &fp[2]); + copy_v2_v2(bezt->vec[2], &fp[4]); + bezt->weight = fp[6]; + bezt->radius = fp[7]; +} + /* these functions match. copy is swapped */ void BKE_mask_object_shape_from_mask(MaskObject *maskobj, MaskObjectShape *maskobj_shape) { @@ -1094,13 +1112,8 @@ void BKE_mask_object_shape_from_mask(MaskObject *maskobj, MaskObjectShape *masko for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { - BezTriple *bezt = &spline->points[i].bezt; - /* *** BKE_mask_object_shape_to_mask - swapped *** */ - copy_v2_v2(fp, bezt->vec[0]); fp += 2; - copy_v2_v2(fp, bezt->vec[1]); fp += 2; - copy_v2_v2(fp, bezt->vec[2]); fp += 2; - fp[0] = bezt->weight; - fp[1] = bezt->radius; fp += 2; + mask_object_shape_from_mask_point(&spline->points[i].bezt, fp); + fp += MASK_OBJECT_SHAPE_ELEM_SIZE; } } } @@ -1120,13 +1133,8 @@ void BKE_mask_object_shape_to_mask(MaskObject *maskobj, MaskObjectShape *maskobj for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { - BezTriple *bezt = &spline->points[i].bezt; - /* *** BKE_mask_object_shape_from_mask - swapped *** */ - copy_v2_v2(bezt->vec[0], fp); fp += 2; - copy_v2_v2(bezt->vec[1], fp); fp += 2; - copy_v2_v2(bezt->vec[2], fp); fp += 2; - bezt->weight = fp[0]; - bezt->radius = fp[1]; fp += 2; + mask_object_shape_to_mask_point(&spline->points[i].bezt, fp); + fp += MASK_OBJECT_SHAPE_ELEM_SIZE; } } } @@ -1287,6 +1295,96 @@ void BKE_mask_object_shape_sort(MaskObject *maskobj) BLI_sortlist(&maskobj->splines_shapes, mask_object_shape_sort_cb); } +int BKE_mask_object_shape_spline_index(MaskObject *maskobj, int index, + MaskSpline **r_maskobj_shape, int *r_index) +{ + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + if (index < spline->tot_point) { + *r_maskobj_shape = spline; + *r_index = index; + return TRUE; + } + index -= spline->tot_point; + } + + return FALSE; +} + +/* when a now points added - resize all shapekey array */ +void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, + int do_init, int do_init_interpolate) +{ + MaskObjectShape *maskobj_shape; + + for (maskobj_shape = maskobj->splines_shapes.first; + maskobj_shape; + maskobj_shape = maskobj_shape->next) + { + /* spline index from maskobj */ + MaskSpline *spline; + int spline_point_index; + + float *data_resized; + + if (BKE_mask_object_shape_spline_index(maskobj, index, + &spline, &spline_point_index)) + { + maskobj_shape->tot_vert++; + data_resized = MEM_mallocN(maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + if (index > 0) { + memcpy(data_resized, + maskobj_shape->data, + index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + if (do_init) { + if (do_init_interpolate) { + /* TODO */ + } + else { + mask_object_shape_from_mask_point(&spline->points[spline_point_index].bezt, &data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE]); + } + } + else { + memset(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE], + 0, + sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + if (index != maskobj_shape->tot_vert - 1) { + memcpy(&data_resized[(index + 1) * MASK_OBJECT_SHAPE_ELEM_SIZE], + maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), + (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + MEM_freeN(maskobj_shape->data); + maskobj_shape->data = data_resized; + } + } +} + +/* move array to account for removed point */ +#if 0 +void BKE_mask_object_shape_changed_remove(MaskObject *maskobj, int index) +{ + MaskObjectShape *maskobj_shape; + + for (maskobj_shape = maskobj->splines_shapes.first; + maskobj_shape; + maskobj_shape = maskobj_shape->next) + { + if (frame == maskobj_shape->frame) { + return maskobj_shape; + } + else if (frame < maskobj_shape->frame) { + break; + } + } +} +#endif + /* rasterization */ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) { diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 4054814604e..e67a47abdef 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -972,6 +972,23 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) setup_vertex_point(C, mask, spline, new_point, co, tangent, NULL, TRUE); + + { + + /* this block could be a function */ + MaskSpline *spline_iter; + int i_abs = 0; + for (spline_iter = maskobj->splines.first; + spline_iter && spline_iter != spline; + spline_iter = spline_iter->next, i_abs += spline_iter->tot_point) + { + /* pass */ + } + + /* TODO - we could pass the spline! */ + BKE_mask_object_shape_changed_add(maskobj, i_abs + point_index + 1, TRUE, FALSE); + } + maskobj->act_point = new_point; WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); From 139c92e7eb69ba03441faeb7e67b84d60488a199 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 25 May 2012 09:06:15 +0000 Subject: [PATCH 081/183] new points now have their animated locations applied all non-active keys. --- source/blender/blenkernel/intern/mask.c | 90 +++++++++++++++++++------ source/blender/editors/mask/mask_ops.c | 2 +- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index c09947ef540..4a91de8cf6d 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1157,7 +1157,6 @@ void BKE_mask_object_shape_to_mask_interp(MaskObject *maskobj, const float fac) { int tot = BKE_mask_object_shape_totvert(maskobj); - printf("%.6f\n", fac); if (maskobj_shape_a->tot_vert == tot && maskobj_shape_b->tot_vert == tot) { float *fp_a = maskobj_shape_a->data; float *fp_b = maskobj_shape_b->data; @@ -1312,25 +1311,70 @@ int BKE_mask_object_shape_spline_index(MaskObject *maskobj, int index, return FALSE; } +/* basic 2D interpolation functions, could make more comprehensive later */ +static void interp_weights_uv_v2_calc(float r_uv[2], const float pt[2], const float pt_a[2], const float pt_b[2]) +{ + float pt_on_line[2]; + r_uv[0] = closest_to_line_v2(pt_on_line, pt, pt_a, pt_b); + r_uv[1] = (len_v2v2(pt_on_line, pt) / len_v2v2(pt_a, pt_b)) * + ((line_point_side_v2(pt_a, pt_b, pt) < 0.0f) ? -1.0 : 1.0); /* this line only sets the sign */ +} + + +static void interp_weights_uv_v2_apply(const float uv[2], float r_pt[2], const float pt_a[2], const float pt_b[2]) +{ + const float dvec[2] = {pt_b[0] - pt_a[0], + pt_b[1] - pt_a[1]}; + + /* u */ + madd_v2_v2v2fl(r_pt, pt_a, dvec, uv[0]); + + /* v */ + r_pt[0] += -dvec[1] * uv[1]; + r_pt[1] += dvec[0] * uv[1]; +} + /* when a now points added - resize all shapekey array */ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, int do_init, int do_init_interpolate) { MaskObjectShape *maskobj_shape; - for (maskobj_shape = maskobj->splines_shapes.first; - maskobj_shape; - maskobj_shape = maskobj_shape->next) + /* spline index from maskobj */ + MaskSpline *spline; + int spline_point_index; + + if (BKE_mask_object_shape_spline_index(maskobj, index, + &spline, &spline_point_index)) { - /* spline index from maskobj */ - MaskSpline *spline; - int spline_point_index; + /* for interpolation */ + /* TODO - assumes closed curve for now */ + float uv[3][2]; /* 3x 2D handles */ + const int pi_curr = spline_point_index; + const int pi_prev = ((spline_point_index - 1) + spline->tot_point) % spline->tot_point; + const int pi_next = (spline_point_index + 1) % spline->tot_point; - float *data_resized; + const int index_offset = index - spline_point_index; + /* const int pi_curr_abs = index; */ + const int pi_prev_abs = pi_prev + index_offset; + const int pi_next_abs = pi_next + index_offset; - if (BKE_mask_object_shape_spline_index(maskobj, index, - &spline, &spline_point_index)) + int i; + if (do_init_interpolate) { + for (i = 0; i < 3; i++) { + interp_weights_uv_v2_calc(uv[i], + spline->points[pi_curr].bezt.vec[i], + spline->points[pi_prev].bezt.vec[i], + spline->points[pi_next].bezt.vec[i]); + } + } + + for (maskobj_shape = maskobj->splines_shapes.first; + maskobj_shape; + maskobj_shape = maskobj_shape->next) { + float *data_resized; + maskobj_shape->tot_vert++; data_resized = MEM_mallocN(maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); if (index > 0) { @@ -1339,12 +1383,24 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } + if (index != maskobj_shape->tot_vert - 1) { + memcpy(&data_resized[(index + 1) * MASK_OBJECT_SHAPE_ELEM_SIZE], + maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), + (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + if (do_init) { + float *fp = &data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE]; + + mask_object_shape_from_mask_point(&spline->points[spline_point_index].bezt, fp); + if (do_init_interpolate) { - /* TODO */ - } - else { - mask_object_shape_from_mask_point(&spline->points[spline_point_index].bezt, &data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE]); + for (i = 0; i < 3; i++) { + interp_weights_uv_v2_apply(uv[i], + &fp[i * 2], + &data_resized[(pi_prev_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)], + &data_resized[(pi_next_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)]); + } } } else { @@ -1353,12 +1409,6 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } - if (index != maskobj_shape->tot_vert - 1) { - memcpy(&data_resized[(index + 1) * MASK_OBJECT_SHAPE_ELEM_SIZE], - maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), - (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); - } - MEM_freeN(maskobj_shape->data); maskobj_shape->data = data_resized; } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index e67a47abdef..8f8be8fefc1 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -986,7 +986,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) } /* TODO - we could pass the spline! */ - BKE_mask_object_shape_changed_add(maskobj, i_abs + point_index + 1, TRUE, FALSE); + BKE_mask_object_shape_changed_add(maskobj, i_abs + point_index + 1, TRUE, TRUE); } maskobj->act_point = new_point; From c6e0d24d02bbbeefdd9010e7f99f4d95185f4c61 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 25 May 2012 10:04:10 +0000 Subject: [PATCH 082/183] add auto-key for masks --- .../editors/transform/transform_conversions.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 0be2967d54b..7cc8b479517 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4910,6 +4910,20 @@ void special_aftertrans_update(bContext *C, TransInfo *t) nodeUpdateID(t->scene->nodetree, &mask->id); WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); } + + /* TODO - dont key all masks... */ + if (IS_AUTOKEY_ON(t->scene)) { + MaskObject *maskobj; + Scene *scene = t->scene; + int frame = CFRA; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskObjectShape *maskobj_shape; + + maskobj_shape = BKE_mask_object_shape_varify_frame(maskobj, frame); + BKE_mask_object_shape_from_mask(maskobj, maskobj_shape); + } + } } } else if (t->spacetype == SPACE_ACTION) { From e70316f3b26f89d775b5ee27e382cadb28ab0fc4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 25 May 2012 11:41:42 +0000 Subject: [PATCH 083/183] fix for crash in auto ketframe. --- source/blender/blenkernel/intern/mask.c | 64 ++++++++++++++----------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 4a91de8cf6d..c9aaa2563aa 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1347,6 +1347,9 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, if (BKE_mask_object_shape_spline_index(maskobj, index, &spline, &spline_point_index)) { + /* sanity check */ + int tot = BKE_mask_object_shape_totvert(maskobj); + /* for interpolation */ /* TODO - assumes closed curve for now */ float uv[3][2]; /* 3x 2D handles */ @@ -1373,44 +1376,49 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, maskobj_shape; maskobj_shape = maskobj_shape->next) { - float *data_resized; + if (tot == maskobj_shape->tot_vert) { + float *data_resized; - maskobj_shape->tot_vert++; - data_resized = MEM_mallocN(maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); - if (index > 0) { - memcpy(data_resized, - maskobj_shape->data, - index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); - } + maskobj_shape->tot_vert++; + data_resized = MEM_mallocN(maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + if (index > 0) { + memcpy(data_resized, + maskobj_shape->data, + index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } - if (index != maskobj_shape->tot_vert - 1) { - memcpy(&data_resized[(index + 1) * MASK_OBJECT_SHAPE_ELEM_SIZE], - maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), - (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); - } + if (index != maskobj_shape->tot_vert - 1) { + memcpy(&data_resized[(index + 1) * MASK_OBJECT_SHAPE_ELEM_SIZE], + maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), + (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } - if (do_init) { - float *fp = &data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE]; + if (do_init) { + float *fp = &data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE]; - mask_object_shape_from_mask_point(&spline->points[spline_point_index].bezt, fp); + mask_object_shape_from_mask_point(&spline->points[spline_point_index].bezt, fp); - if (do_init_interpolate) { - for (i = 0; i < 3; i++) { - interp_weights_uv_v2_apply(uv[i], - &fp[i * 2], - &data_resized[(pi_prev_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)], - &data_resized[(pi_next_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)]); + if (do_init_interpolate) { + for (i = 0; i < 3; i++) { + interp_weights_uv_v2_apply(uv[i], + &fp[i * 2], + &data_resized[(pi_prev_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)], + &data_resized[(pi_next_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)]); + } } } + else { + memset(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE], + 0, + sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + MEM_freeN(maskobj_shape->data); + maskobj_shape->data = data_resized; } else { - memset(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE], - 0, - sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + printf("%s: vert mismatch %d != %d\n", __func__, maskobj_shape->tot_vert, tot); } - - MEM_freeN(maskobj_shape->data); - maskobj_shape->data = data_resized; } } } From 94fc1f5f4a9a33cb78ef095b3534448655b7fb3c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 25 May 2012 11:51:56 +0000 Subject: [PATCH 084/183] fix error in prev commit --- source/blender/blenkernel/intern/mask.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index c9aaa2563aa..eacdaeabd1e 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1348,7 +1348,7 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, &spline, &spline_point_index)) { /* sanity check */ - int tot = BKE_mask_object_shape_totvert(maskobj); + int tot = BKE_mask_object_shape_totvert(maskobj) - 1; /* for interpolation */ /* TODO - assumes closed curve for now */ From bb97cf31dee09b87c3ef634ee4fb86b6295ad045 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 25 May 2012 12:06:10 +0000 Subject: [PATCH 085/183] print frame bumbers when printing shapes that mismatch --- source/blender/blenkernel/intern/mask.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index eacdaeabd1e..55ea4173491 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1118,7 +1118,8 @@ void BKE_mask_object_shape_from_mask(MaskObject *maskobj, MaskObjectShape *masko } } else { - printf("%s: vert mismatch %d != %d\n", __func__, maskobj_shape->tot_vert, tot); + printf("%s: vert mismatch %d != %d (frame %d)\n", + __func__, maskobj_shape->tot_vert, tot, maskobj_shape->frame); } } @@ -1139,7 +1140,8 @@ void BKE_mask_object_shape_to_mask(MaskObject *maskobj, MaskObjectShape *maskobj } } else { - printf("%s: vert mismatch %d != %d\n", __func__, maskobj_shape->tot_vert, tot); + printf("%s: vert mismatch %d != %d (frame %d)\n", + __func__, maskobj_shape->tot_vert, tot, maskobj_shape->frame); } } @@ -1177,8 +1179,9 @@ void BKE_mask_object_shape_to_mask_interp(MaskObject *maskobj, } } else { - printf("%s: vert mismatch %d != %d != %d\n", - __func__, maskobj_shape_a->tot_vert, maskobj_shape_b->tot_vert, tot); + printf("%s: vert mismatch %d != %d != %d (frame %d - %d)\n", + __func__, maskobj_shape_a->tot_vert, maskobj_shape_b->tot_vert, tot, + maskobj_shape_a->frame, maskobj_shape_b->frame); } } @@ -1417,7 +1420,8 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, maskobj_shape->data = data_resized; } else { - printf("%s: vert mismatch %d != %d\n", __func__, maskobj_shape->tot_vert, tot); + printf("%s: vert mismatch %d != %d (frame %d)\n", + __func__, maskobj_shape->tot_vert, tot, maskobj_shape->frame); } } } From b230ebf726a0823a632fd70f5c04f3d0ec8c9898 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 25 May 2012 12:48:24 +0000 Subject: [PATCH 086/183] mask slide now auto-keys --- source/blender/blenkernel/intern/mask.c | 54 +++++++++++++------ source/blender/editors/include/ED_mask.h | 3 ++ source/blender/editors/mask/mask_ops.c | 8 +++ source/blender/editors/mask/mask_shapekey.c | 16 ++++++ .../editors/transform/transform_conversions.c | 9 +--- 5 files changed, 65 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 55ea4173491..bc9629176cc 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1351,6 +1351,7 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, &spline, &spline_point_index)) { /* sanity check */ + /* the point has already been removed in this array so subtract one when comparing with the shapes */ int tot = BKE_mask_object_shape_totvert(maskobj) - 1; /* for interpolation */ @@ -1376,8 +1377,8 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, } for (maskobj_shape = maskobj->splines_shapes.first; - maskobj_shape; - maskobj_shape = maskobj_shape->next) + maskobj_shape; + maskobj_shape = maskobj_shape->next) { if (tot == maskobj_shape->tot_vert) { float *data_resized; @@ -1386,14 +1387,14 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, data_resized = MEM_mallocN(maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); if (index > 0) { memcpy(data_resized, - maskobj_shape->data, - index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + maskobj_shape->data, + index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } if (index != maskobj_shape->tot_vert - 1) { memcpy(&data_resized[(index + 1) * MASK_OBJECT_SHAPE_ELEM_SIZE], - maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), - (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), + (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } if (do_init) { @@ -1404,16 +1405,16 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, if (do_init_interpolate) { for (i = 0; i < 3; i++) { interp_weights_uv_v2_apply(uv[i], - &fp[i * 2], - &data_resized[(pi_prev_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)], - &data_resized[(pi_next_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)]); + &fp[i * 2], + &data_resized[(pi_prev_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)], + &data_resized[(pi_next_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)]); } } } else { memset(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE], - 0, - sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + 0, + sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } MEM_freeN(maskobj_shape->data); @@ -1428,24 +1429,43 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, } /* move array to account for removed point */ -#if 0 void BKE_mask_object_shape_changed_remove(MaskObject *maskobj, int index) { MaskObjectShape *maskobj_shape; + /* the point has already been removed in this array so add one when comparing with the shapes */ + int tot = BKE_mask_object_shape_totvert(maskobj) + 1; + for (maskobj_shape = maskobj->splines_shapes.first; maskobj_shape; maskobj_shape = maskobj_shape->next) { - if (frame == maskobj_shape->frame) { - return maskobj_shape; + if (tot == maskobj_shape->tot_vert) { + float *data_resized; + + maskobj_shape->tot_vert--; + data_resized = MEM_mallocN(maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + if (index > 0) { + memcpy(data_resized, + maskobj_shape->data, + (index - 1) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + if (index != maskobj_shape->tot_vert - 1) { + memcpy(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE], + maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), + (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + MEM_freeN(maskobj_shape->data); + maskobj_shape->data = data_resized; } - else if (frame < maskobj_shape->frame) { - break; + else { + printf("%s: vert mismatch %d != %d (frame %d)\n", + __func__, maskobj_shape->tot_vert, tot, maskobj_shape->frame); } } } -#endif /* rasterization */ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 01495561912..ed1d2ba688e 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -41,4 +41,7 @@ void ED_operatormacros_mask(void); /* mask_draw.c */ void ED_mask_draw(const bContext *C); +/* mask_shapekey.c */ +int ED_mask_object_shape_auto_key_all(struct Mask *mask, const int frame); + #endif /* ED_TEXT_H */ diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 8f8be8fefc1..e52d673ad9e 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -40,6 +40,7 @@ #include "BKE_depsgraph.h" #include "BKE_mask.h" +#include "DNA_scene_types.h" #include "DNA_mask_types.h" #include "DNA_object_types.h" /* SELECT */ @@ -49,6 +50,7 @@ #include "ED_screen.h" #include "ED_mask.h" #include "ED_clip.h" +#include "ED_keyframing.h" #include "RNA_access.h" #include "RNA_define.h" @@ -770,8 +772,14 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) case LEFTMOUSE: if (event->val == KM_RELEASE) { + Scene *scene = CTX_data_scene(C); + free_slide_point_data(op->customdata); + if (IS_AUTOKEY_ON(scene)) { + ED_mask_object_shape_auto_key_all(data->mask, CFRA); + } + WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); DAG_id_tag_update(&data->mask->id, 0); diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index c80ca979077..7a91fbeed13 100755 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -142,3 +142,19 @@ void MASK_OT_shape_key_clear(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +int ED_mask_object_shape_auto_key_all(Mask *mask, const int frame) +{ + MaskObject *maskobj; + int change = FALSE; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskObjectShape *maskobj_shape; + + maskobj_shape = BKE_mask_object_shape_varify_frame(maskobj, frame); + BKE_mask_object_shape_from_mask(maskobj, maskobj_shape); + change = TRUE; + } + + return change; +} diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 7cc8b479517..875e9e4a63f 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4913,16 +4913,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* TODO - dont key all masks... */ if (IS_AUTOKEY_ON(t->scene)) { - MaskObject *maskobj; Scene *scene = t->scene; - int frame = CFRA; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskObjectShape *maskobj_shape; - - maskobj_shape = BKE_mask_object_shape_varify_frame(maskobj, frame); - BKE_mask_object_shape_from_mask(maskobj, maskobj_shape); - } + ED_mask_object_shape_auto_key_all(mask, CFRA); } } } From 6fa349f85e8feff90ba00a52b3669e28ea09c223 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 25 May 2012 15:20:29 +0000 Subject: [PATCH 087/183] support for deleting splines and points while maintaining animation --- source/blender/blenkernel/BKE_mask.h | 2 ++ source/blender/blenkernel/intern/mask.c | 19 ++++++++++--------- source/blender/editors/mask/mask_ops.c | 13 +++++++++++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 7745eb0b972..fb9db2fcf98 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -115,6 +115,8 @@ int BKE_mask_object_shape_spline_index(struct MaskObject *maskobj, int index, void BKE_mask_object_shape_changed_add(struct MaskObject *maskobj, int index, int do_init, int do_init_interpolate); +void BKE_mask_object_shape_changed_remove(struct MaskObject *maskobj, int index, int count); + /* rasterization */ void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index bc9629176cc..146b67bd15c 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1428,33 +1428,34 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, } } + /* move array to account for removed point */ -void BKE_mask_object_shape_changed_remove(MaskObject *maskobj, int index) +void BKE_mask_object_shape_changed_remove(MaskObject *maskobj, int index, int count) { MaskObjectShape *maskobj_shape; /* the point has already been removed in this array so add one when comparing with the shapes */ - int tot = BKE_mask_object_shape_totvert(maskobj) + 1; + int tot = BKE_mask_object_shape_totvert(maskobj); for (maskobj_shape = maskobj->splines_shapes.first; maskobj_shape; maskobj_shape = maskobj_shape->next) { - if (tot == maskobj_shape->tot_vert) { + if (tot == maskobj_shape->tot_vert - count) { float *data_resized; - maskobj_shape->tot_vert--; + maskobj_shape->tot_vert -= count; data_resized = MEM_mallocN(maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); if (index > 0) { memcpy(data_resized, maskobj_shape->data, - (index - 1) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } - if (index != maskobj_shape->tot_vert - 1) { + if (index != maskobj_shape->tot_vert) { memcpy(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE], - maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), - (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + maskobj_shape->data + ((index + count) * MASK_OBJECT_SHAPE_ELEM_SIZE), + (maskobj_shape->tot_vert - index) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } MEM_freeN(maskobj_shape->data); @@ -1462,7 +1463,7 @@ void BKE_mask_object_shape_changed_remove(MaskObject *maskobj, int index) } else { printf("%s: vert mismatch %d != %d (frame %d)\n", - __func__, maskobj_shape->tot_vert, tot, maskobj_shape->frame); + __func__, maskobj_shape->tot_vert - count, tot, maskobj_shape->frame); } } } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index e52d673ad9e..69befc16b87 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1305,11 +1305,13 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); MaskObject *maskobj; + int mask_object_shape_ofs = 0; for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline = maskobj->splines.first; while (spline) { + const int tot_point_orig = spline->tot_point; int i, count = 0; MaskSpline *next_spline = spline->next; @@ -1322,6 +1324,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) } if (count == 0) { + /* delete the whole spline */ BLI_remlink(&maskobj->splines, spline); BKE_mask_spline_free(spline); @@ -1330,6 +1333,8 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) maskobj->act_spline = NULL; maskobj->act_point = NULL; } + + BKE_mask_object_shape_changed_remove(maskobj, mask_object_shape_ofs, tot_point_orig); } else { MaskSplinePoint *new_points; @@ -1337,7 +1342,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) new_points = MEM_callocN(count * sizeof(MaskSplinePoint), "deleteMaskPoints"); - for (i = 0, j = 0; i < spline->tot_point; i++) { + for (i = 0, j = 0; i < tot_point_orig; i++) { MaskSplinePoint *point = &spline->points[i]; if (!MASKPOINT_ISSEL(point)) { @@ -1354,12 +1359,16 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) maskobj->act_point = NULL; BKE_mask_point_free(point); + spline->tot_point--; + + BKE_mask_object_shape_changed_remove(maskobj, mask_object_shape_ofs + j, 1); } } + mask_object_shape_ofs += spline->tot_point; + MEM_freeN(spline->points); spline->points = new_points; - spline->tot_point = j; ED_mask_select_flush_all(mask); } From 10c6a8ce1a803f5d1dacedf3a4030394b5a16e7f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 25 May 2012 17:44:37 +0000 Subject: [PATCH 088/183] fix for adding/removing spline items with multiple splines in a mask-object --- source/blender/blenkernel/BKE_mask.h | 4 ++++ source/blender/blenkernel/intern/mask.c | 24 +++++++++++++++++++----- source/blender/editors/mask/mask_ops.c | 25 +++++++++---------------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index fb9db2fcf98..21c053e259b 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -110,6 +110,10 @@ struct MaskObjectShape *BKE_mask_object_shape_varify_frame(struct MaskObject *ma void BKE_mask_object_shape_unlink(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape); void BKE_mask_object_shape_sort(struct MaskObject *maskobj); +int BKE_mask_object_shape_spline_from_index(struct MaskObject *maskobj, int index, + struct MaskSpline **r_maskobj_shape, int *r_index); +int BKE_mask_object_shape_spline_to_index(struct MaskObject *maskobj, struct MaskSpline *spline); + int BKE_mask_object_shape_spline_index(struct MaskObject *maskobj, int index, struct MaskSpline **r_maskobj_shape, int *r_index); void BKE_mask_object_shape_changed_add(struct MaskObject *maskobj, int index, diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 146b67bd15c..e5ac03561ad 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1297,8 +1297,8 @@ void BKE_mask_object_shape_sort(MaskObject *maskobj) BLI_sortlist(&maskobj->splines_shapes, mask_object_shape_sort_cb); } -int BKE_mask_object_shape_spline_index(MaskObject *maskobj, int index, - MaskSpline **r_maskobj_shape, int *r_index) +int BKE_mask_object_shape_spline_from_index(MaskObject *maskobj, int index, + MaskSpline **r_maskobj_shape, int *r_index) { MaskSpline *spline; @@ -1314,6 +1314,20 @@ int BKE_mask_object_shape_spline_index(MaskObject *maskobj, int index, return FALSE; } +int BKE_mask_object_shape_spline_to_index(MaskObject *maskobj, MaskSpline *spline) +{ + MaskSpline *spline_iter; + int i_abs = 0; + for (spline_iter = maskobj->splines.first; + spline_iter && spline_iter != spline; + i_abs += spline_iter->tot_point, spline_iter = spline_iter->next) + { + /* pass */ + } + + return i_abs; +} + /* basic 2D interpolation functions, could make more comprehensive later */ static void interp_weights_uv_v2_calc(float r_uv[2], const float pt[2], const float pt_a[2], const float pt_b[2]) { @@ -1347,8 +1361,8 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, MaskSpline *spline; int spline_point_index; - if (BKE_mask_object_shape_spline_index(maskobj, index, - &spline, &spline_point_index)) + if (BKE_mask_object_shape_spline_from_index(maskobj, index, + &spline, &spline_point_index)) { /* sanity check */ /* the point has already been removed in this array so subtract one when comparing with the shapes */ @@ -1402,7 +1416,7 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, mask_object_shape_from_mask_point(&spline->points[spline_point_index].bezt, fp); - if (do_init_interpolate) { + if (do_init_interpolate && spline->tot_point > 2) { for (i = 0; i < 3; i++) { interp_weights_uv_v2_apply(uv[i], &fp[i * 2], diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 69befc16b87..ba027a47802 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -980,22 +980,8 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) setup_vertex_point(C, mask, spline, new_point, co, tangent, NULL, TRUE); - - { - - /* this block could be a function */ - MaskSpline *spline_iter; - int i_abs = 0; - for (spline_iter = maskobj->splines.first; - spline_iter && spline_iter != spline; - spline_iter = spline_iter->next, i_abs += spline_iter->tot_point) - { - /* pass */ - } - - /* TODO - we could pass the spline! */ - BKE_mask_object_shape_changed_add(maskobj, i_abs + point_index + 1, TRUE, TRUE); - } + /* TODO - we could pass the spline! */ + BKE_mask_object_shape_changed_add(maskobj, BKE_mask_object_shape_spline_to_index(maskobj, spline) + point_index + 1, TRUE, TRUE); maskobj->act_point = new_point; @@ -1114,6 +1100,13 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) maskobj->act_point = new_point; setup_vertex_point(C, mask, spline, new_point, co, NULL, ref_point, FALSE); + + { + //int point_index = (((int)(new_point - spline->points) + 1) % spline->tot_point); + int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); + BKE_mask_object_shape_changed_add(maskobj, BKE_mask_object_shape_spline_to_index(maskobj, spline) + point_index, TRUE, TRUE); + } + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return TRUE; From 3595db735057b9153463ccdf4b568d6fdc9798f0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 26 May 2012 23:18:07 +0000 Subject: [PATCH 089/183] draw the mask keyframes in the clip view --- source/blender/editors/space_clip/clip_draw.c | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index c0ac262d996..337b21465a3 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -33,12 +33,14 @@ #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" /* SELECT */ +#include "DNA_mask_types.h" #include "MEM_guardedalloc.h" #include "BKE_context.h" #include "BKE_movieclip.h" #include "BKE_tracking.h" +#include "BKE_mask.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -194,6 +196,32 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc glRecti(x, 0, x + framelen, 8); clip_draw_curfra_label(sc, x, 8.0f); + + /* movie clip animation */ + if ((sc->mode == SC_MODE_MASKEDITING) && sc->mask) { + MaskObject *maskobj = BKE_mask_object_active(sc->mask); + if (maskobj) { + MaskObjectShape *maskobj_shape; + + glColor4ub(255, 255, 0, 96); + glBegin(GL_LINES); + + for (maskobj_shape = maskobj->splines_shapes.first; + maskobj_shape; + maskobj_shape = maskobj_shape->next) + { + i = maskobj_shape->frame; + + /* glRecti((i - sfra) * framelen, 0, (i - sfra + 1) * framelen, 4); */ + + /* use a line so we always see the keyframes */ + glVertex2i((i - sfra) * framelen, 0); + glVertex2i((i - sfra) * framelen, 4); + } + + glEnd(); + } + } } static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar) From e7ba0100c7d9254e2220ef6ca484883db40910bd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 27 May 2012 10:35:12 +0000 Subject: [PATCH 090/183] tweaks to frame drawing from sebastian-k --- source/blender/editors/space_clip/clip_draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 337b21465a3..fd47bc376c7 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -203,7 +203,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc if (maskobj) { MaskObjectShape *maskobj_shape; - glColor4ub(255, 255, 0, 96); + glColor4ub(255, 175, 0, 255); glBegin(GL_LINES); for (maskobj_shape = maskobj->splines_shapes.first; @@ -216,7 +216,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc /* use a line so we always see the keyframes */ glVertex2i((i - sfra) * framelen, 0); - glVertex2i((i - sfra) * framelen, 4); + glVertex2i((i - sfra) * framelen, (i == CFRA) ? 22 : 10); } glEnd(); From 1edf40594d3d693ec0d67173604641b7ad8740b8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 27 May 2012 12:59:16 +0000 Subject: [PATCH 091/183] up-down arrow keys now jump between mask keyframes (when in the mask view). --- .../editors/animation/keyframes_draw.c | 68 +++++++++++++++++++ .../editors/include/ED_keyframes_draw.h | 4 ++ source/blender/editors/screen/screen_ops.c | 14 +++- source/blender/makesdna/DNA_mask_types.h | 2 + 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index cb7dc7ac206..579527dfc56 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -60,6 +60,7 @@ #include "DNA_speaker_types.h" #include "DNA_world_types.h" #include "DNA_gpencil_types.h" +#include "DNA_mask_types.h" #include "BKE_key.h" #include "BKE_material.h" @@ -184,6 +185,50 @@ static void nupdate_ak_gpframe(void *node, void *data) ak->modified += 1; } +/* ......... */ + +/* Comparator callback used for ActKeyColumns and GPencil frame */ +static short compare_ak_maskobjshape(void *node, void *data) +{ + ActKeyColumn *ak = (ActKeyColumn *)node; + MaskObjectShape *maskobj_shape = (MaskObjectShape *)data; + + if (maskobj_shape->frame < ak->cfra) + return -1; + else if (maskobj_shape->frame > ak->cfra) + return 1; + else + return 0; +} + +/* New node callback used for building ActKeyColumns from GPencil frames */ +static DLRBT_Node *nalloc_ak_maskobjshape(void *data) +{ + ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"); + MaskObjectShape *maskobj_shape = (MaskObjectShape *)data; + + /* store settings based on state of BezTriple */ + ak->cfra = maskobj_shape->frame; + ak->sel = (maskobj_shape->flag & SELECT) ? SELECT : 0; + + /* set 'modified', since this is used to identify long keyframes */ + ak->modified = 1; + + return (DLRBT_Node *)ak; +} + +/* Node updater callback used for building ActKeyColumns from GPencil frames */ +static void nupdate_ak_maskobjshape(void *node, void *data) +{ + ActKeyColumn *ak = (ActKeyColumn *)node; + MaskObjectShape *maskobj_shape = (MaskObjectShape *)data; + + /* set selection status and 'touched' status */ + if (maskobj_shape->flag & SELECT) ak->sel = SELECT; + ak->modified += 1; +} + + /* --------------- */ /* Add the given BezTriple to the given 'list' of Keyframes */ @@ -204,6 +249,15 @@ static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf) BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf); } +/* Add the given MaskObjectShape Frame to the given 'list' of Keyframes */ +static void add_maskobj_to_keycolumns_list(DLRBT_Tree *keys, MaskObjectShape *maskobj_shape) +{ + if (ELEM(NULL, keys, maskobj_shape)) + return; + else + BLI_dlrbTree_add(keys, compare_ak_maskobjshape, nalloc_ak_maskobjshape, nupdate_ak_maskobjshape, maskobj_shape); +} + /* ActBeztColumns (Helpers for Long Keyframes) ------------------------------ */ /* maximum size of default buffer for BezTriple columns */ @@ -940,3 +994,17 @@ void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys) } } +void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskObject *maskobj, DLRBT_Tree *keys) +{ + MaskObjectShape *maskobj_shape; + + if (maskobj && keys) { + for (maskobj_shape = maskobj->splines_shapes.first; + maskobj_shape; + maskobj_shape = maskobj_shape->next) + { + add_maskobj_to_keycolumns_list(keys, maskobj_shape); + } + } +} + diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index cd64427de78..d90b5648c23 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -42,6 +42,7 @@ struct bActionGroup; struct Object; struct ListBase; struct bGPDlayer; +struct MaskObject; struct Scene; struct View2D; struct DLRBT_Tree; @@ -139,6 +140,9 @@ void summary_to_keylist(struct bAnimContext *ac, struct DLRBT_Tree *keys, struct /* Grease Pencil Layer */ // XXX not restored void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys); +/* Mask */ +// XXX not restored +void mask_to_keylist(struct bDopeSheet *UNUSED(ads), struct MaskObject *maskobj, struct DLRBT_Tree *keys); /* ActKeyColumn API ---------------- */ /* Comparator callback used for ActKeyColumns and cframe float-value pointer */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index becb82767e9..7caff30807d 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -46,6 +46,7 @@ #include "DNA_scene_types.h" #include "DNA_meta_types.h" #include "DNA_mesh_types.h" +#include "DNA_mask_types.h" #include "DNA_userdef_types.h" #include "BKE_context.h" @@ -59,6 +60,7 @@ #include "BKE_screen.h" #include "BKE_tessmesh.h" #include "BKE_sound.h" +#include "BKE_mask.h" #include "WM_api.h" #include "WM_types.h" @@ -1945,7 +1947,17 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) if (ob) ob_to_keylist(&ads, ob, &keys, NULL); - + + { + SpaceClip *sc = CTX_wm_space_clip(C); + if (sc) { + if ((sc->mode == SC_MODE_MASKEDITING) && sc->mask) { + MaskObject *maskobj = BKE_mask_object_active(sc->mask); + mask_to_keylist(&ads, maskobj, &keys); + } + } + } + /* build linked-list for searching */ BLI_dlrbTree_linkedlist_sync(&keys); diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 9f163adc77b..441b15a8aa9 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -92,6 +92,8 @@ typedef struct MaskObjectShape { float *data; /* u coordinate along spline segment and weight of this point */ int tot_vert; /* to ensure no buffer overruns's: alloc size is (tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE) */ int frame; /* different flags of this point */ + char flag; + char pad[7]; } MaskObjectShape; typedef struct MaskObject { From aab3f71b9db40f9d5b14ae86727bb64c2de3d827 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 27 May 2012 16:59:36 +0000 Subject: [PATCH 092/183] Fix threading issue with Mask node --- source/blender/compositor/operations/COM_MaskOperation.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index 7c71e884e5c..e6456e73be3 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -69,9 +69,12 @@ void *MaskOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers if (this->rasterizedMask == NULL) { int width = this->getWidth(); int height = this->getHeight(); + float *buffer; - this->rasterizedMask = (float *)MEM_callocN(sizeof(float) * width * height, "rasterized mask"); - BKE_mask_rasterize(mask, width, height, this->rasterizedMask); + buffer = (float *)MEM_callocN(sizeof(float) * width * height, "rasterized mask"); + BKE_mask_rasterize(mask, width, height, buffer); + + this->rasterizedMask = buffer; } BLI_mutex_unlock(getMutex()); From 8fb7b4073ec0f73d41e2d0dc0325c699d8067b86 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 28 May 2012 05:37:16 +0000 Subject: [PATCH 093/183] make selection operator follow mesh selection options from trunk. --- source/blender/blenkernel/BKE_mask.h | 4 + source/blender/blenkernel/intern/mask.c | 32 ++++++++ source/blender/editors/mask/mask_editor.c | 11 ++- source/blender/editors/mask/mask_intern.h | 3 +- source/blender/editors/mask/mask_ops.c | 2 +- source/blender/editors/mask/mask_select.c | 89 +++++++++++++---------- 6 files changed, 97 insertions(+), 44 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 21c053e259b..9c944a98564 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -73,6 +73,9 @@ float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *p struct MaskSplinePointUW *BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw); void BKE_mask_point_add_uw(struct MaskSplinePoint *point, float u, float w); +void BKE_mask_point_select_set(struct MaskSplinePoint *point, int select); +void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, int select); + /* general */ struct Mask *BKE_mask_new(const char *name); @@ -134,5 +137,6 @@ void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer) #define MASKPOINT_HANDLE_ONLY_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) && (((p)->bezt.f2 & SELECT) == 0) ) #define MASKPOINT_HANDLE_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) ) #define MASKPOINT_HANDLE_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 +#define MASKPOINT_HANDLE_DESEL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 #endif diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index e5ac03561ad..ec01f303bae 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -41,6 +41,7 @@ #include "DNA_mask_types.h" #include "DNA_scene_types.h" +#include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_movieclip_types.h" @@ -618,6 +619,37 @@ void BKE_mask_point_add_uw(MaskSplinePoint *point, float u, float w) BKE_mask_point_sort_uw(point, &point->uw[point->tot_uw - 1]); } +void BKE_mask_point_select_set(MaskSplinePoint *point, int select) +{ + int i; + + if (select) { + MASKPOINT_SEL(point); + } + else { + MASKPOINT_DESEL(point); + } + + for (i = 0; i < point->tot_uw; i++) { + if (select) { + point->uw[i].flag |= SELECT; + } + else { + point->uw[i].flag &= ~SELECT; + } + } +} + +void BKE_mask_point_select_set_handle(MaskSplinePoint *point, int select) +{ + if (select) { + MASKPOINT_HANDLE_SEL(point); + } + else { + MASKPOINT_HANDLE_DESEL(point); + } +} + /* only mask block itself */ static Mask *mask_alloc(const char *name) { diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index 749c2c0237e..0290934cf9a 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -189,10 +189,15 @@ void ED_keymap_mask(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MASK_OT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_delete", DELKEY, KM_PRESS, 0, 0); - /* select */ - WM_keymap_add_item(keymap, "MASK_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); + /* selection */ + kmi = WM_keymap_add_item(keymap, "MASK_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); kmi = WM_keymap_add_item(keymap, "MASK_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", AKEY, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index fee4b63529d..d6392b07a80 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -73,7 +73,8 @@ void MASK_OT_select_all(struct wmOperatorType *ot); int ED_mask_spline_select_check(struct MaskSplinePoint *points, int tot_point); int ED_mask_select_check(struct Mask *mask); -void ED_mask_point_select(struct MaskSplinePoint *point, int action); +void ED_mask_point_select_set(struct MaskSplinePoint *point, int action); +void ED_mask_point_select_set_handle(struct MaskSplinePoint *point, int select); void ED_mask_select_toggle_all(struct Mask *mask, int action); void ED_mask_select_flush_all(struct Mask *mask); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index ba027a47802..365b3fc31c7 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -646,7 +646,7 @@ static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) else if (!MASKPOINT_ISSEL(slidedata->point)) { ED_mask_select_toggle_all(mask, SEL_DESELECT); - ED_mask_point_select(slidedata->point, SEL_SELECT); + BKE_mask_point_select_set(slidedata->point, TRUE); ED_mask_select_flush_all(mask); } diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index f1ee620e2ce..67df1d458db 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -86,38 +86,6 @@ int ED_mask_select_check(Mask *mask) return FALSE; } -void ED_mask_point_select(MaskSplinePoint *point, int action) -{ - int i; - - switch (action) { - case SEL_SELECT: - MASKPOINT_SEL(point); - break; - case SEL_DESELECT: - MASKPOINT_DESEL(point); - break; - case SEL_INVERT: - MASKPOINT_INVSEL(point); - break; - } - - for (i = 0; i < point->tot_uw; i++) { - switch (action) { - case SEL_SELECT: - point->uw[i].flag |= SELECT; - break; - case SEL_DESELECT: - point->uw[i].flag &= ~SELECT; - break; - case SEL_INVERT: - point->uw[i].flag ^= SELECT; - break; - } - } -} - - void ED_mask_select_toggle_all(Mask *mask, int action) { MaskObject *maskobj; @@ -138,7 +106,7 @@ void ED_mask_select_toggle_all(Mask *mask, int action) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - ED_mask_point_select(point, action); + BKE_mask_point_select_set(point, (action == SEL_SELECT) ? TRUE : FALSE); } } } @@ -219,7 +187,10 @@ static int select_exec(bContext *C, wmOperator *op) MaskSpline *spline; MaskSplinePoint *point = NULL; float co[2]; - int extend = RNA_boolean_get(op->ptr, "extend"); + short extend = RNA_boolean_get(op->ptr, "extend"); + short deselect = RNA_boolean_get(op->ptr, "deselect"); + short toggle = RNA_boolean_get(op->ptr, "toggle"); + int is_handle = 0; const float threshold = 19; @@ -228,14 +199,52 @@ static int select_exec(bContext *C, wmOperator *op) point = ED_mask_point_find_nearest(C, mask, co, threshold, &maskobj, &spline, &is_handle, NULL); if (point) { - if (!extend) + if (extend == 0 && deselect == 0 && toggle == 0) ED_mask_select_toggle_all(mask, SEL_DESELECT); if (is_handle) { - MASKPOINT_HANDLE_SEL(point); + if (extend) { + maskobj->act_spline = spline; + maskobj->act_point = point; + + BKE_mask_point_select_set_handle(point, TRUE); + } + else if (deselect) { + BKE_mask_point_select_set_handle(point, FALSE); + } + else { + maskobj->act_spline = spline; + maskobj->act_point = point; + + if (!MASKPOINT_HANDLE_ISSEL(point)) { + BKE_mask_point_select_set_handle(point, TRUE); + } + else if (toggle) { + BKE_mask_point_select_set_handle(point, FALSE); + } + } } else { - ED_mask_point_select(point, SEL_SELECT); + if (extend) { + maskobj->act_spline = spline; + maskobj->act_point = point; + + BKE_mask_point_select_set(point, TRUE); + } + else if (deselect) { + BKE_mask_point_select_set(point, FALSE); + } + else { + maskobj->act_spline = spline; + maskobj->act_point = point; + + if (!MASKPOINT_ISSEL(point)) { + BKE_mask_point_select_set(point, TRUE); + } + else if (toggle) { + BKE_mask_point_select_set(point, FALSE); + } + } } maskobj->act_spline = spline; @@ -298,8 +307,10 @@ void MASK_OT_select(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; /* properties */ - RNA_def_boolean(ot->srna, "extend", 0, - "Extend", "Extend selection rather than clearing the existing selection"); + RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from selection"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Selection", "Toggles selection"); + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, "Location", "Location of vertex in normalized space", -1.0f, 1.0f); } From 8ab667c17491c16573289471fea3647830b589f5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 28 May 2012 09:53:59 +0000 Subject: [PATCH 094/183] many small improvements to adding points - splines are open by default (double ctrl+click closes them) - adding new points can be done even when a point in the middle of the spline is selected. - adding new points re-orients the handles of previous point. - fix for crash with open curve with one point only. Workflow is Ctrl+Click about and double click to finish - works fast and gives nicer result then before. --- source/blender/blenkernel/BKE_mask.h | 4 +- source/blender/blenkernel/intern/mask.c | 52 ++++- source/blender/editors/mask/mask_intern.h | 2 - source/blender/editors/mask/mask_ops.c | 224 +++++++++++++++++----- 4 files changed, 222 insertions(+), 60 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 9c944a98564..963b5a8e0ba 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -91,8 +91,10 @@ void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_n void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe); void BKE_mask_parent_init(struct MaskParent *parent); void BKE_mask_calc_handle_adjacent_length(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); +void BKE_mask_calc_tangent_polyline(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, float t[2]); void BKE_mask_calc_handle_point(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); -void BKE_mask_calc_handle_point_auto(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); +void BKE_mask_calc_handle_point_auto(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, + const short do_recalc_length); void BKE_mask_get_handle_point_adjacent(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, struct MaskSplinePoint **r_point_prev, struct MaskSplinePoint **r_point_next); void BKE_mask_calc_handles(struct Mask *mask); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index ec01f303bae..24804ff3e5a 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -123,7 +123,7 @@ MaskSpline *BKE_mask_spline_add(MaskObject *maskobj) spline->tot_point = 1; /* cyclic shapes are more usually used */ - spline->flag |= MASK_SPLINE_CYCLIC; + // spline->flag |= MASK_SPLINE_CYCLIC; // disable because its not so nice for drawing. could be done differently spline->weight_interp = MASK_SPLINE_INTERP_LINEAR; @@ -855,7 +855,9 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev next_bezt = &next_point->bezt; #if 1 - BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + if (prev_bezt || next_bezt) { + BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + } #else if (handle_type == HD_VECT) { BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); @@ -922,6 +924,37 @@ void BKE_mask_get_handle_point_adjacent(Mask *UNUSED(mask), MaskSpline *spline, *r_point_next = next_point; } +/* calculates the tanget of a point by its previous and next + * (ignoring handles - as if its a poly line) */ +void BKE_mask_calc_tangent_polyline(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, float t[2]) +{ + float tvec_a[2], tvec_b[2]; + + MaskSplinePoint *prev_point, *next_point; + + BKE_mask_get_handle_point_adjacent(mask, spline, point, + &prev_point, &next_point); + + if (prev_point) { + sub_v2_v2v2(tvec_a, point->bezt.vec[1], prev_point->bezt.vec[1]); + normalize_v2(tvec_a); + } + else { + zero_v2(tvec_a); + } + + if (next_point) { + sub_v2_v2v2(tvec_b, next_point->bezt.vec[1], point->bezt.vec[1]); + normalize_v2(tvec_b); + } + else { + zero_v2(tvec_b); + } + + add_v2_v2v2(t, tvec_a, tvec_b); + normalize_v2(t); +} + void BKE_mask_calc_handle_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) { MaskSplinePoint *prev_point, *next_point; @@ -945,7 +978,7 @@ static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dis void BKE_mask_calc_handle_adjacent_length(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) { - /* TODO! - make this aspect aware! */ + /* TODO! - make this interpolate between siblings - not always midpoint! */ int length_tot = 0; float length_average = 0.0f; @@ -977,11 +1010,14 @@ void BKE_mask_calc_handle_adjacent_length(Mask *mask, MaskSpline *spline, MaskSp * * Useful for giving sane defaults. */ -void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) +void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, + const short do_recalc_length) { - /* TODO! - make this aspect aware! */ MaskSplinePoint *prev_point, *next_point; const char h_back[2] = {point->bezt.h1, point->bezt.h2}; + const float length_average = (do_recalc_length) ? 0.0f /* dummy value */ : + (len_v3v3(point->bezt.vec[0], point->bezt.vec[1]) + + len_v3v3(point->bezt.vec[1], point->bezt.vec[2])) / 2.0f; BKE_mask_get_handle_point_adjacent(mask, spline, point, &prev_point, &next_point); @@ -992,6 +1028,12 @@ void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplineP point->bezt.h1 = h_back[0]; point->bezt.h2 = h_back[1]; + + /* preserve length by applying it back */ + if (do_recalc_length == FALSE) { + enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); + enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + } } void BKE_mask_calc_handles(Mask *mask) diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index d6392b07a80..4eab64b2bcd 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -73,8 +73,6 @@ void MASK_OT_select_all(struct wmOperatorType *ot); int ED_mask_spline_select_check(struct MaskSplinePoint *points, int tot_point); int ED_mask_select_check(struct Mask *mask); -void ED_mask_point_select_set(struct MaskSplinePoint *point, int action); -void ED_mask_point_select_set_handle(struct MaskSplinePoint *point, int select); void ED_mask_select_toggle_all(struct Mask *mask, int action); void ED_mask_select_flush_all(struct Mask *mask); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 365b3fc31c7..1e46b893dcd 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -301,7 +301,7 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in return FALSE; } -static int find_nearest_diff_point(bContext *C, Mask *mask, float normal_co[2], int threshold, int feather, +static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_co[2], int threshold, int feather, MaskObject **maskobj_r, MaskSpline **spline_r, MaskSplinePoint **point_r, float *u_r, float tangent[2]) { @@ -937,7 +937,7 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask add_v2_v2(bezt->vec[0], vec); sub_v2_v2(bezt->vec[2], vec); #else - BKE_mask_calc_handle_point_auto(mask, spline, new_point); + BKE_mask_calc_handle_point_auto(mask, spline, new_point, TRUE); BKE_mask_calc_handle_adjacent_length(mask, spline, new_point); #endif @@ -952,7 +952,22 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask /* **** add subdivide vertex **** */ -static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) +static void mask_spline_add_point_at_index(MaskSpline *spline, int point_index) +{ + MaskSplinePoint *new_point_array; + + new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); + + memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * (point_index + 1)); + memcpy(new_point_array + point_index + 2, spline->points + point_index + 1, + sizeof(MaskSplinePoint) * (spline->tot_point - point_index - 1)); + + MEM_freeN(spline->points); + spline->points = new_point_array; + spline->tot_point++; +} + +static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) { MaskObject *maskobj; MaskSpline *spline; @@ -961,22 +976,14 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, float co[2]) float tangent[2]; if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &maskobj, &spline, &point, NULL, tangent)) { - MaskSplinePoint *new_point_array, *new_point; + MaskSplinePoint *new_point; int point_index = point - spline->points; ED_mask_select_toggle_all(mask, SEL_DESELECT); - new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); + mask_spline_add_point_at_index(spline, point_index); - memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * (point_index + 1)); - memcpy(new_point_array + point_index + 2, spline->points + point_index + 1, - sizeof(MaskSplinePoint) * (spline->tot_point - point_index - 1)); - - MEM_freeN(spline->points); - spline->points = new_point_array; - spline->tot_point++; - - new_point = &new_point_array[point_index + 1]; + new_point = &spline->points[point_index + 1]; setup_vertex_point(C, mask, spline, new_point, co, tangent, NULL, TRUE); @@ -1036,7 +1043,110 @@ static void finSelectedSplinePoint(MaskObject *maskobj, MaskSpline **spline, Mas } } -static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) +static int add_vertex_extrude(bContext *C, Mask *mask, const float co[2]) +{ + MaskObject *maskobj; + MaskSpline *spline; + MaskSplinePoint *point; + MaskSplinePoint *new_point = NULL, *ref_point = NULL; + + /* check on which side we want to add the point */ + int point_index; + float tangent_point[2]; + float tangent_co[2]; + int do_cyclic_correct = FALSE; + int do_recalc_src = FALSE; /* when extruding from endpoints only */ + int do_prev; /* use prev point rather then next?? */ + + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + maskobj = BKE_mask_object_active(mask); + + if (!maskobj) { + return FALSE; + } + else { + finSelectedSplinePoint(maskobj, &spline, &point, TRUE); + } + + point_index = (point - spline->points); + + MASKPOINT_DESEL(point); + + if ((spline->flag & MASK_SPLINE_CYCLIC) || + (point_index > 0 && point_index != spline->tot_point - 1)) + { + BKE_mask_calc_tangent_polyline(mask, spline, point, tangent_point); + sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]); + + if (dot_v2v2(tangent_point, tangent_co) < 0.0f) { + do_prev = TRUE; + } + else { + do_prev = FALSE; + } + } + else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == 0)) { + do_prev = TRUE; + do_recalc_src = TRUE; + } + else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == spline->tot_point - 1)) { + do_prev = FALSE; + do_recalc_src = TRUE; + } + else { + /* should never get here */ + BLI_assert(0); + } + + /* use the point before the active one */ + if (do_prev) { + point_index--; + if (point_index < 0) { + point_index += spline->tot_point; /* wrap index */ + if ((spline->flag & MASK_SPLINE_CYCLIC) == 0) { + do_cyclic_correct = TRUE; + point_index = 0; + } + } + } + +// print_v2("", tangent_point); +// printf("%d\n", point_index); + + mask_spline_add_point_at_index(spline, point_index); + + if (do_cyclic_correct) { + ref_point = &spline->points[point_index + 1]; + new_point = &spline->points[point_index]; + *ref_point = *new_point; + memset(new_point, 0, sizeof(*new_point)); + } + else { + ref_point = &spline->points[point_index]; + new_point = &spline->points[point_index + 1]; + } + + maskobj->act_point = new_point; + + setup_vertex_point(C, mask, spline, new_point, co, NULL, ref_point, FALSE); + + if (maskobj->splines_shapes.first) { + point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); + BKE_mask_object_shape_changed_add(maskobj, BKE_mask_object_shape_spline_to_index(maskobj, spline) + point_index, TRUE, TRUE); + } + + if (do_recalc_src) { + /* TODO, update keyframes in time */ + BKE_mask_calc_handle_point_auto(mask, spline, ref_point, FALSE); + } + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return TRUE; +} + +static int add_vertex_new(bContext *C, Mask *mask, const float co[2]) { MaskObject *maskobj; MaskSpline *spline; @@ -1061,48 +1171,16 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) if (!spline) { /* no selected splines in active maskobj, create new spline */ spline = BKE_mask_spline_add(maskobj); - maskobj->act_spline = spline; - new_point = spline->points; } - if (!new_point) { - MaskSplinePoint *new_point_array; - - if (point == &spline->points[spline->tot_point - 1]) { - MASKPOINT_DESEL(point); - new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); - memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * spline->tot_point); - MEM_freeN(spline->points); - spline->points = new_point_array; - spline->tot_point++; - - new_point = &spline->points[spline->tot_point - 1]; - ref_point = &spline->points[spline->tot_point - 2]; - } - else if (point == &spline->points[0]) { - MASKPOINT_DESEL(point); - new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); - memcpy(new_point_array + 1, spline->points, sizeof(MaskSplinePoint) * spline->tot_point); - MEM_freeN(spline->points); - spline->points = new_point_array; - spline->tot_point++; - - new_point = &spline->points[0]; - ref_point = &spline->points[1]; - } - else { - spline = BKE_mask_spline_add(maskobj); - maskobj->act_spline = spline; - new_point = spline->points; - } - } + maskobj->act_spline = spline; + new_point = spline->points; maskobj->act_point = new_point; setup_vertex_point(C, mask, spline, new_point, co, NULL, ref_point, FALSE); { - //int point_index = (((int)(new_point - spline->points) + 1) % spline->tot_point); int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); BKE_mask_object_shape_changed_add(maskobj, BKE_mask_object_shape_spline_to_index(maskobj, spline) + point_index, TRUE, TRUE); } @@ -1115,13 +1193,55 @@ static int add_vertex_extrude(bContext *C, Mask *mask, float co[2]) static int add_vertex_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + float co[2]; + maskobj = BKE_mask_object_active(mask); + RNA_float_get_array(op->ptr, "location", co); - if (!add_vertex_subdivide(C, mask, co)) { - if (!add_vertex_extrude(C, mask, co)) - return OPERATOR_CANCELLED; + if (maskobj && maskobj->act_point && MASKPOINT_ISSEL(maskobj->act_point)) { + + /* cheap trick - double click for cyclic */ + MaskSpline *spline = maskobj->act_spline; + MaskSplinePoint *point = maskobj->act_point; + + int is_sta = (point == spline->points); + int is_end = (point == &spline->points[spline->tot_point - 1]); + + /* then check are we overlapping the mouse */ + if ((is_sta || is_end) && equals_v2v2(co, point->bezt.vec[1])) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + /* nothing to do */ + return OPERATOR_CANCELLED; + } + else { + /* recalc the connecting point as well to make a nice even curve */ + MaskSplinePoint *point_other = is_end ? spline->points : &spline->points[spline->tot_point - 1]; + spline->flag |= MASK_SPLINE_CYCLIC; + + /* TODO, update keyframes in time */ + BKE_mask_calc_handle_point_auto(mask, spline, point, FALSE); + BKE_mask_calc_handle_point_auto(mask, spline, point_other, FALSE); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + return OPERATOR_FINISHED; + } + } + + if (!add_vertex_subdivide(C, mask, co)) { + if (!add_vertex_extrude(C, mask, co)) { + return OPERATOR_CANCELLED; + } + } + } + else { + if (!add_vertex_subdivide(C, mask, co)) { + if (!add_vertex_new(C, mask, co)) { + return OPERATOR_CANCELLED; + } + } } return OPERATOR_FINISHED; From b9d1830d77fbbef2f616f648f688389ef05e7d06 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 May 2012 06:31:42 +0000 Subject: [PATCH 095/183] check for parent before applying offset --- source/blender/blenkernel/intern/mask.c | 33 +++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 24804ff3e5a..e9937cbc617 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -812,13 +812,13 @@ void BKE_mask_coord_to_movieclip(MovieClip *clip, MovieClipUser *user, float r_c } } -static void evaluate_mask_parent(MaskParent *parent, float ctime, float r_co[2]) +static int evaluate_mask_parent(MaskParent *parent, float ctime, float r_co[2]) { if (!parent) - return; + return FALSE; if ((parent->flag & MASK_PARENT_ACTIVE) == 0) - return; + return FALSE; if (parent->id_type == ID_MC) { if (parent->id) { @@ -836,10 +836,14 @@ static void evaluate_mask_parent(MaskParent *parent, float ctime, float r_co[2]) MovieTrackingMarker *marker = BKE_tracking_get_marker(track, ctime); BKE_mask_coord_from_movieclip(clip, &user, r_co, marker->pos); add_v2_v2(r_co, parent->offset); + + return TRUE; } } } } + + return FALSE; } static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev_point, MaskSplinePoint *next_point) @@ -979,7 +983,7 @@ static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dis void BKE_mask_calc_handle_adjacent_length(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) { /* TODO! - make this interpolate between siblings - not always midpoint! */ - int length_tot = 0; + int length_tot = 0; float length_average = 0.0f; MaskSplinePoint *prev_point, *next_point; @@ -1098,16 +1102,19 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) for (spline = maskobj->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - BezTriple *bezt = &point->bezt; - float co[2], delta[2]; + float co[2]; - copy_v2_v2(co, bezt->vec[1]); - evaluate_mask_parent(&point->parent, ctime, co); - sub_v2_v2v2(delta, co, bezt->vec[1]); + if (evaluate_mask_parent(&point->parent, ctime, co)) { + BezTriple *bezt = &point->bezt; + float delta[2]; - add_v2_v2(bezt->vec[0], delta); - add_v2_v2(bezt->vec[1], delta); - add_v2_v2(bezt->vec[2], delta); + copy_v2_v2(co, bezt->vec[1]); + sub_v2_v2v2(delta, co, bezt->vec[1]); + + add_v2_v2(bezt->vec[0], delta); + add_v2_v2(bezt->vec[1], delta); + add_v2_v2(bezt->vec[2], delta); + } } } } @@ -1220,7 +1227,7 @@ void BKE_mask_object_shape_to_mask(MaskObject *maskobj, MaskObjectShape *maskobj } BLI_INLINE void interp_v2_v2v2_flfl(float target[2], const float a[2], const float b[2], - const float t, const float s) + const float t, const float s) { target[0] = s * a[0] + t * b[0]; target[1] = s * a[1] + t * b[1]; From edad58c5b17835b598b824cc0726a6e269e54ee8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 May 2012 08:55:16 +0000 Subject: [PATCH 096/183] initial support for animating parented mask points. --- source/blender/blenkernel/BKE_mask.h | 3 + source/blender/blenkernel/intern/mask.c | 172 +++++++++++++++--- source/blender/blenloader/intern/writefile.c | 5 + source/blender/editors/mask/mask_draw.c | 28 ++- source/blender/editors/mask/mask_ops.c | 11 +- .../blender/editors/mask/mask_relationships.c | 1 + source/blender/makesdna/DNA_mask_types.h | 3 + 7 files changed, 187 insertions(+), 36 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 963b5a8e0ba..5020fd97895 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -39,6 +39,9 @@ struct MovieClip; struct MovieClipUser; struct Scene; +struct MaskSplinePoint *BKE_mask_spline_point_array(struct MaskSpline *spline); +struct MaskSplinePoint *BKE_mask_spline_point_array_from_point(struct MaskSpline *spline, struct MaskSplinePoint *point_ref); + /* mask objects */ struct MaskObject *BKE_mask_object_new(struct Mask *mask, const char *name); struct MaskObject *BKE_mask_object_active(struct Mask *mask); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index e9937cbc617..566c0920bbf 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -58,6 +58,25 @@ #include "raskter.h" +MaskSplinePoint *BKE_mask_spline_point_array(MaskSpline *spline) +{ + return spline->points_deform ? spline->points_deform : spline->points; +} + +MaskSplinePoint *BKE_mask_spline_point_array_from_point(MaskSpline *spline, MaskSplinePoint *point_ref) +{ + if ((point_ref >= spline->points) && (point_ref < &spline->points[spline->tot_point])) { + return spline->points; + } + + if ((point_ref >= spline->points_deform) && (point_ref < &spline->points_deform[spline->tot_point])) { + return spline->points_deform; + } + + BLI_assert(!"wrong array"); + return NULL; +} + /* mask objects */ MaskObject *BKE_mask_object_new(Mask *mask, const char *name) @@ -201,6 +220,8 @@ int BKE_mask_spline_feather_resolution(MaskSpline *spline) float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + MaskSplinePoint *point, *prev; float *diff_points, *fp; int a, len, resol = BKE_mask_spline_resolution(spline); @@ -227,7 +248,7 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) if (spline->flag & MASK_SPLINE_CYCLIC) a++; - prev = spline->points; + prev = points_array; point = prev + 1; while (a--) { @@ -236,7 +257,7 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) int j; if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) - point = spline->points; + point = points_array; prevbezt = &prev->bezt; bezt = &point->bezt; @@ -262,6 +283,8 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + float *feather, *fp; int i, j, tot, resol = BKE_mask_spline_feather_resolution(spline); @@ -269,7 +292,7 @@ float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *to feather = fp = MEM_callocN(2 * tot * sizeof(float), "mask spline feather diff points"); for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point = &points_array[i]; for (j = 0; j < resol; j++, fp += 2) { float u = (float) j / resol, weight; @@ -291,12 +314,14 @@ float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *to float *BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + int i, tot = 0; float *feather, *fp; /* count */ for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point = &points_array[i]; tot += point->tot_uw + 1; } @@ -305,7 +330,7 @@ float *BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point feather = fp = MEM_callocN(2 * tot * sizeof(float), "mask spline feather points"); for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point = &points_array[i]; BezTriple *bezt = &point->bezt; float weight, n[2]; int j; @@ -431,15 +456,17 @@ float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint * float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_diff_point) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + BezTriple *bezt, *next; float *diff_points, *fp; int j, resol = BKE_mask_spline_resolution(spline); bezt = &point->bezt; - if (point == &spline->points[spline->tot_point - 1]) { + if (point == &points_array[spline->tot_point - 1]) { if (spline->flag & MASK_SPLINE_CYCLIC) - next = &(spline->points[0].bezt); + next = &(points_array[0].bezt); else next = NULL; } @@ -465,12 +492,14 @@ float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, i void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float u, float co[2]) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + BezTriple *bezt = &point->bezt, *next; float q0[2], q1[2], q2[2], r0[2], r1[2]; - if (point == &spline->points[spline->tot_point - 1]) { + if (point == &points_array[spline->tot_point - 1]) { if (spline->flag & MASK_SPLINE_CYCLIC) - next = &(spline->points[0].bezt); + next = &(points_array[0].bezt); else next = NULL; } @@ -493,12 +522,14 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, float n[2]) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + BezTriple *bezt = &point->bezt, *next; float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2]; - if (point == &spline->points[spline->tot_point - 1]) { + if (point == &points_array[spline->tot_point - 1]) { if (spline->flag & MASK_SPLINE_CYCLIC) - next = &(spline->points[0].bezt); + next = &(points_array[0].bezt); else next = NULL; } @@ -531,13 +562,15 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + BezTriple *bezt = &point->bezt, *next; float cur_u, cur_w, next_u, next_w, fac; int i; - if (point == &spline->points[spline->tot_point - 1]) { + if (point == &points_array[spline->tot_point - 1]) { if (spline->flag & MASK_SPLINE_CYCLIC) - next = &(spline->points[0].bezt); + next = &(points_array[0].bezt); else next = NULL; } @@ -686,13 +719,22 @@ void BKE_mask_spline_free(MaskSpline *spline) int i = 0; for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - + MaskSplinePoint *point; + point = &spline->points[i]; BKE_mask_point_free(point); + + if (spline->points_deform) { + point = &spline->points_deform[i]; + BKE_mask_point_free(point); + } } MEM_freeN(spline->points); + if (spline->points_deform) { + MEM_freeN(spline->points_deform); + } + MEM_freeN(spline); } @@ -812,7 +854,7 @@ void BKE_mask_coord_to_movieclip(MovieClip *clip, MovieClipUser *user, float r_c } } -static int evaluate_mask_parent(MaskParent *parent, float ctime, float r_co[2]) +static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[2]) { if (!parent) return FALSE; @@ -846,6 +888,19 @@ static int evaluate_mask_parent(MaskParent *parent, float ctime, float r_co[2]) return FALSE; } +int BKE_mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delta[2]) +{ + float parent_co[2]; + + if (BKE_mask_evaluate_parent(parent, ctime, parent_co)) { + sub_v2_v2v2(r_delta, parent->parent_orig, parent_co); + return TRUE; + } + else { + return FALSE; + } +} + static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev_point, MaskSplinePoint *next_point) { BezTriple *bezt = &point->bezt; @@ -1057,6 +1112,63 @@ void BKE_mask_calc_handles(Mask *mask) } } +void BKE_mask_update_deform(Mask *mask) +{ + MaskObject *maskobj; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + const int i_prev = (i - 1) % spline->tot_point; + const int i_next = (i + 1) % spline->tot_point; + + BezTriple *bezt_prev = &spline->points[i_prev].bezt; + BezTriple *bezt = &spline->points[i ].bezt; + BezTriple *bezt_next = &spline->points[i_next].bezt; + + BezTriple *bezt_def_prev = &spline->points_deform[i_prev].bezt; + BezTriple *bezt_def = &spline->points_deform[i ].bezt; + BezTriple *bezt_def_next = &spline->points_deform[i_next].bezt; + + float w_src[4]; + int j; + + for (j = 0; j <= 2; j += 2) { /* (0, 2) */ + printf("--- %d %d, %d, %d\n", i, j, i_prev, i_next); + barycentric_weights_v2(bezt_prev->vec[1], bezt->vec[1], bezt_next->vec[1], + bezt->vec[j], w_src); + interp_v3_v3v3v3(bezt_def->vec[j], + bezt_def_prev->vec[1], bezt_def->vec[1], bezt_def_next->vec[1], w_src); + } + } + } + } +} + +void BKE_mask_spline_ensure_deform(MaskSpline *spline) +{ +// printf("SPLINE ALLOC %p %d\n", spline->points_deform, (int)(MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform))); + + if ((spline->points_deform == NULL) || + (MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform)) != spline->tot_point) + { + printf("alloc new spline\n"); + + if (spline->points_deform) { + MEM_freeN(spline->points_deform); + } + + spline->points_deform = MEM_mallocN(sizeof(*spline->points_deform) * spline->tot_point, __func__); + } + else { + printf("alloc spline done\n"); + } +} + void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) { MaskObject *maskobj; @@ -1100,20 +1212,30 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) /* animation done... */ for (spline = maskobj->splines.first; spline; spline = spline->next) { + + BKE_mask_spline_ensure_deform(spline); + for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - float co[2]; + MaskSplinePoint *point_deform = &spline->points_deform[i]; + float delta[2]; - if (evaluate_mask_parent(&point->parent, ctime, co)) { - BezTriple *bezt = &point->bezt; - float delta[2]; + if (BKE_mask_evaluate_parent_delta(&point->parent, ctime, delta)) { - copy_v2_v2(co, bezt->vec[1]); - sub_v2_v2v2(delta, co, bezt->vec[1]); + *point_deform = *point; + point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; - add_v2_v2(bezt->vec[0], delta); - add_v2_v2(bezt->vec[1], delta); - add_v2_v2(bezt->vec[2], delta); + print_v2("", delta); + + sub_v2_v2(point_deform->bezt.vec[0], delta); + sub_v2_v2(point_deform->bezt.vec[1], delta); + add_v2_v2(point_deform->bezt.vec[2], delta); + + //point_deform->bezt.vec[1][1] += 1; + } + else { + *point_deform = *point; + point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; } } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 7c9945ef517..320278544ae 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2778,9 +2778,14 @@ static void write_masks(WriteData *wd, ListBase *idbase) for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; + void *points_deform = spline->points_deform; + spline->points_deform = NULL; + writestruct(wd, DATA, "MaskSpline", 1, spline); writestruct(wd, DATA, "MaskSplinePoint", spline->tot_point, spline->points); + spline->points_deform = points_deform; + for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 7077450c807..f09c1fa232f 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -65,6 +65,7 @@ static void set_spline_color(MaskObject *maskobj, MaskSpline *spline) static void draw_spline_parents(MaskObject *UNUSED(maskobj), MaskSpline *spline) { int i; + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); if (!spline->tot_point) return; @@ -76,14 +77,15 @@ static void draw_spline_parents(MaskObject *UNUSED(maskobj), MaskSpline *spline) glBegin(GL_LINES); for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point = &points_array[i]; + BezTriple *bezt = &point->bezt; if (point->parent.flag & MASK_PARENT_ACTIVE) { - glVertex2f(point->bezt.vec[1][0], - point->bezt.vec[1][1]); + glVertex2f(bezt->vec[1][0], + bezt->vec[1][1]); - glVertex2f(point->bezt.vec[1][0] - point->parent.offset[0], - point->bezt.vec[1][1] - point->parent.offset[1]); + glVertex2f(bezt->vec[1][0] - point->parent.offset[0], + bezt->vec[1][1] - point->parent.offset[1]); } } @@ -95,6 +97,8 @@ static void draw_spline_parents(MaskObject *UNUSED(maskobj), MaskSpline *spline) /* return non-zero if spline is selected */ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + int i, hsize, tot_feather_point; float *feather_points, *fp; @@ -108,9 +112,12 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) /* feather points */ feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); for (i = 0; i < spline->tot_point; i++) { - int j; + + /* watch it! this is intentionally not the deform array, only check for sel */ MaskSplinePoint *point = &spline->points[i]; + int j; + for (j = 0; j < point->tot_uw + 1; j++) { int sel = FALSE; @@ -142,12 +149,17 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) /* control points */ for (i = 0; i < spline->tot_point; i++) { + + /* watch it! this is intentionally not the deform array, only check for sel */ MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point_deform = &points_array[i]; + BezTriple *bezt = &point_deform->bezt; + float handle[2]; - float *vert = point->bezt.vec[1]; + float *vert = bezt->vec[1]; int has_handle = BKE_mask_point_has_handle(point); - BKE_mask_point_handle(point, handle); + BKE_mask_point_handle(point_deform, handle); /* draw handle segment */ if (has_handle) { diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 1e46b893dcd..ded45e73323 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -144,17 +144,20 @@ MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float norma MaskSpline *spline; for (spline = maskobj->splines.first; spline; spline = spline->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + int i; for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *cur_point = &spline->points[i]; + MaskSplinePoint *cur_point_deform = &points_array[i]; float cur_len, vec[2], handle[2]; - vec[0] = cur_point->bezt.vec[1][0] * scalex; - vec[1] = cur_point->bezt.vec[1][1] * scaley; + vec[0] = cur_point_deform->bezt.vec[1][0] * scalex; + vec[1] = cur_point_deform->bezt.vec[1][1] * scaley; if (BKE_mask_point_has_handle(cur_point)) { - BKE_mask_point_handle(cur_point, handle); + BKE_mask_point_handle(cur_point_deform, handle); handle[0] *= scalex; handle[1] *= scaley; @@ -233,6 +236,8 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in MaskSpline *spline; for (spline = maskobj->splines.first; spline; spline = spline->next) { + //MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + int i, tot_feather_point; float *feather_points, *fp; diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 136376336d8..9d3195a26de 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -151,6 +151,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) add_v2_v2(bezt->vec[2], tvec); negate_v2_v2(point->parent.offset, tvec); + copy_v2_v2(point->parent.parent_orig, parmask_pos); } } } diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 441b15a8aa9..eef7a024d72 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -59,6 +59,7 @@ typedef struct MaskParent { * in case of parenting to movie tracking data contains name of track */ float offset[2]; /* offset from parent position, so object/control point can be parented to a * motion track and also be animated (see ZanQdo's request below) */ + float parent_orig[2]; /* track location at the moment of parenting */ } MaskParent; typedef struct MaskSplinePointUW { @@ -83,6 +84,8 @@ typedef struct MaskSpline { MaskParent parent; /* parenting information of the whole spline */ int weight_interp, pad; /* weight interpolation */ + + MaskSplinePoint *points_deform; /* deformed copy of 'points' BezTriple data - not saved */ } MaskSpline; /* one per frame */ From 74438b63365a99a60260fdf3d55f3a61fd444f2b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 May 2012 11:00:02 +0000 Subject: [PATCH 097/183] fix for parent + animation handles. --- source/blender/blenkernel/BKE_mask.h | 1 + source/blender/blenkernel/intern/mask.c | 25 ++++++++++++++++--------- source/blender/editors/mask/mask_draw.c | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 5020fd97895..d463843e561 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -101,6 +101,7 @@ void BKE_mask_calc_handle_point_auto(struct Mask *mask, struct MaskSpline *splin void BKE_mask_get_handle_point_adjacent(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, struct MaskSplinePoint **r_point_prev, struct MaskSplinePoint **r_point_next); void BKE_mask_calc_handles(struct Mask *mask); +void BKE_mask_spline_ensure_deform(struct MaskSpline *spline); /* animation */ int BKE_mask_object_shape_totvert(struct MaskObject *maskobj); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 566c0920bbf..236fc4825ca 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -893,7 +893,7 @@ int BKE_mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delt float parent_co[2]; if (BKE_mask_evaluate_parent(parent, ctime, parent_co)) { - sub_v2_v2v2(r_delta, parent->parent_orig, parent_co); + sub_v2_v2v2(r_delta, parent_co, parent->parent_orig); return TRUE; } else { @@ -1107,6 +1107,11 @@ void BKE_mask_calc_handles(Mask *mask) for (i = 0; i < spline->tot_point; i++) { BKE_mask_calc_handle_point(mask, spline, &spline->points[i]); + + /* could be done in a different function... */ + if (spline->points_deform) { + BKE_mask_calc_handle_point(mask, spline, &spline->points[i]); + } } } } @@ -1174,8 +1179,6 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) MaskObject *maskobj; for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline; - int i; /* animation if available */ if (do_newframe) { @@ -1210,6 +1213,14 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) } } /* animation done... */ + } + + BKE_mask_calc_handles(mask); + + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + int i; for (spline = maskobj->splines.first; spline; spline = spline->next) { @@ -1227,11 +1238,9 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) print_v2("", delta); - sub_v2_v2(point_deform->bezt.vec[0], delta); - sub_v2_v2(point_deform->bezt.vec[1], delta); + add_v2_v2(point_deform->bezt.vec[0], delta); + add_v2_v2(point_deform->bezt.vec[1], delta); add_v2_v2(point_deform->bezt.vec[2], delta); - - //point_deform->bezt.vec[1][1] += 1; } else { *point_deform = *point; @@ -1240,8 +1249,6 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) } } } - - BKE_mask_calc_handles(mask); } void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const int do_newframe) diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index f09c1fa232f..6555e7f804b 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -266,6 +266,9 @@ static void draw_maskobjs(Mask *mask) MaskSpline *spline; for (spline = maskobj->splines.first; spline; spline = spline->next) { + + BKE_mask_spline_ensure_deform(spline); + /* draw curve itself first... */ draw_spline_curve(maskobj, spline); @@ -273,6 +276,17 @@ static void draw_maskobjs(Mask *mask) /* ...and then handles over the curve so they're nicely visible */ draw_spline_points(maskobj, spline); + + /* show undeform for testing */ + if (0) { + void *back = spline->points_deform; + + spline->points_deform = NULL; + draw_spline_curve(maskobj, spline); + draw_spline_parents(maskobj, spline); + draw_spline_points(maskobj, spline); + spline->points_deform = back; + } } } } From 08fa15b64ac9eb55725071a816f178e4491e80b5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 May 2012 11:48:34 +0000 Subject: [PATCH 098/183] fix crash with using uninitialized curves --- source/blender/editors/mask/mask_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 6555e7f804b..34c478dceaa 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -267,7 +267,7 @@ static void draw_maskobjs(Mask *mask) for (spline = maskobj->splines.first; spline; spline = spline->next) { - BKE_mask_spline_ensure_deform(spline); +// BKE_mask_spline_ensure_deform(spline); /* draw curve itself first... */ draw_spline_curve(maskobj, spline); From 777d0255ff50e6d57840db3c364aa56039836bbd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 May 2012 13:18:11 +0000 Subject: [PATCH 099/183] fix for parenting, offset isnt needed anymore --- source/blender/blenkernel/intern/mask.c | 1 - source/blender/editors/mask/mask_draw.c | 6 ++++-- source/blender/editors/mask/mask_relationships.c | 8 -------- source/blender/makesdna/DNA_mask_types.h | 2 -- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 236fc4825ca..ffd2630742d 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -877,7 +877,6 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[ if (track) { MovieTrackingMarker *marker = BKE_tracking_get_marker(track, ctime); BKE_mask_coord_from_movieclip(clip, &user, r_co, marker->pos); - add_v2_v2(r_co, parent->offset); return TRUE; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 34c478dceaa..fe11ded64f4 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -62,6 +62,7 @@ static void set_spline_color(MaskObject *maskobj, MaskSpline *spline) } } +#if 0 static void draw_spline_parents(MaskObject *UNUSED(maskobj), MaskSpline *spline) { int i; @@ -93,6 +94,7 @@ static void draw_spline_parents(MaskObject *UNUSED(maskobj), MaskSpline *spline) glDisable(GL_LINE_STIPPLE); } +#endif /* return non-zero if spline is selected */ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) @@ -272,7 +274,7 @@ static void draw_maskobjs(Mask *mask) /* draw curve itself first... */ draw_spline_curve(maskobj, spline); - draw_spline_parents(maskobj, spline); +// draw_spline_parents(maskobj, spline); /* ...and then handles over the curve so they're nicely visible */ draw_spline_points(maskobj, spline); @@ -283,7 +285,7 @@ static void draw_maskobjs(Mask *mask) spline->points_deform = NULL; draw_spline_curve(maskobj, spline); - draw_spline_parents(maskobj, spline); +// draw_spline_parents(maskobj, spline); draw_spline_points(maskobj, spline); spline->points_deform = back; } diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 9d3195a26de..96782c5b294 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -135,7 +135,6 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) if (MASKPOINT_ISSEL(point)) { BezTriple *bezt = &point->bezt; - float tvec[2]; point->parent.id_type = ID_MC; point->parent.id = &clip->id; @@ -144,13 +143,6 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) point->parent.flag |= MASK_PARENT_ACTIVE; - sub_v2_v2v2(tvec, parmask_pos, bezt->vec[1]); - - add_v2_v2(bezt->vec[0], tvec); - add_v2_v2(bezt->vec[1], tvec); - add_v2_v2(bezt->vec[2], tvec); - - negate_v2_v2(point->parent.offset, tvec); copy_v2_v2(point->parent.parent_orig, parmask_pos); } } diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index eef7a024d72..cf3f5e77544 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -57,8 +57,6 @@ typedef struct MaskParent { * in case of parenting to movie tracking data contains name of object */ char sub_parent[64]; /* sub-entity of parent to which parenting happened * in case of parenting to movie tracking data contains name of track */ - float offset[2]; /* offset from parent position, so object/control point can be parented to a - * motion track and also be animated (see ZanQdo's request below) */ float parent_orig[2]; /* track location at the moment of parenting */ } MaskParent; From f5917b15b5f603f0b9b567915b4aa93320d6dc54 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 May 2012 13:23:34 +0000 Subject: [PATCH 100/183] support for marker parent offset --- source/blender/blenkernel/intern/mask.c | 6 +++--- source/blender/editors/mask/mask_relationships.c | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index ffd2630742d..439495e8af1 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -876,7 +876,9 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[ if (track) { MovieTrackingMarker *marker = BKE_tracking_get_marker(track, ctime); - BKE_mask_coord_from_movieclip(clip, &user, r_co, marker->pos); + float marker_pos_ofs[2]; + add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset); + BKE_mask_coord_from_movieclip(clip, &user, r_co, marker_pos_ofs); return TRUE; } @@ -1235,8 +1237,6 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) *point_deform = *point; point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; - print_v2("", delta); - add_v2_v2(point_deform->bezt.vec[0], delta); add_v2_v2(point_deform->bezt.vec[1], delta); add_v2_v2(point_deform->bezt.vec[2], delta); diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 96782c5b294..4d08e2fa439 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -112,6 +112,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) MovieTrackingObject *tracking; /* done */ + float marker_pos_ofs[2]; float parmask_pos[2]; if ((NULL == (sc = CTX_wm_space_clip(C))) || @@ -123,7 +124,9 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker->pos); + add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset); + + BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs); for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; @@ -134,8 +137,6 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) MaskSplinePoint *point = &spline->points[i]; if (MASKPOINT_ISSEL(point)) { - BezTriple *bezt = &point->bezt; - point->parent.id_type = ID_MC; point->parent.id = &clip->id; strcpy(point->parent.parent, tracking->name); From 876665ac25a731bcf5937d4e06de7337d6e8af6a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 29 May 2012 14:00:47 +0000 Subject: [PATCH 101/183] Initial commit of new keying nodes First node is called Keying Screen (Add -> Matte -> Keying Screen) and it's aimed to resolve issues with gradients on green screens by producing image with gradient which is later used as an input for screen color in keying nodes. This node gets motion tracks from given movie clip and trackign object and uses them to define color and position of points of gradient: for position marker's position on current frame is sued, for color average color of pattern area is used. Gradient is calculating in the following way: - On first step voronoi diagram is creating for given tracks. - On second step triangulation of this diagram happens by connecting sites to edges which defines area this site belongs to. - On third step gradient filling of this triangles happens. One of triangle vertices is colored with average track color, two rest vertoces are colored with average color between two neighbor sites. Current pixel's color in triangle is calculating as linear combination of vertices colors and barycentric coordinates of this pixel. This node is implemented for both tile and legacy compositor systems. Second node is basically a combination of several existing nodes to make keying more straighforward and reduce spagetti mess in the compositor, but it also ships some fresh approaches calculating matte which seems to be working better for not actually green screens. This node supports: - Chroma preblur - Dispilling - Clip white/black - Dilate/Erode - Matte post blur This node doesn't support chroma pre-blur for legacy compositor (yet). There're still lots of stuff to be improved here, but this nodes night already be used i think. Some details might be found on this wiki page: http://wiki.blender.org/index.php/User:Nazg-gul/Keying This patch also contains some currently unused code from color math module, but it was used for tests and might be used for tests in the future. Think it's ok to have it in branch at least. --- source/blender/blenkernel/BKE_node.h | 2 + source/blender/blenkernel/intern/node.c | 2 + source/blender/blenlib/BLI_math_base.h | 3 + source/blender/blenlib/BLI_math_color.h | 4 + source/blender/blenlib/BLI_math_geom.h | 3 + source/blender/blenlib/BLI_voronoi.h | 70 ++ source/blender/blenlib/CMakeLists.txt | 1 + source/blender/blenlib/intern/math_color.c | 84 ++ source/blender/blenlib/intern/math_geom.c | 39 + source/blender/blenlib/intern/voronoi.c | 833 ++++++++++++++++++ source/blender/compositor/CMakeLists.txt | 12 + .../compositor/intern/COM_Converter.cpp | 7 + .../compositor/nodes/COM_KeyingNode.cpp | 211 +++++ .../blender/compositor/nodes/COM_KeyingNode.h | 44 + .../compositor/nodes/COM_KeyingScreenNode.cpp | 57 ++ .../compositor/nodes/COM_KeyingScreenNode.h | 36 + .../operations/COM_KeyingDispillOperation.cpp | 89 ++ .../operations/COM_KeyingDispillOperation.h | 49 ++ .../operations/COM_KeyingOperation.cpp | 114 +++ .../operations/COM_KeyingOperation.h | 57 ++ .../operations/COM_KeyingScreenOperation.cpp | 217 +++++ .../operations/COM_KeyingScreenOperation.h | 79 ++ source/blender/editors/space_node/drawnode.c | 37 +- source/blender/makesdna/DNA_node_types.h | 11 + source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_nodetree.c | 61 ++ .../makesrna/intern/rna_nodetree_types.h | 2 + source/blender/nodes/CMakeLists.txt | 2 + source/blender/nodes/NOD_composite.h | 3 + .../nodes/composite/node_composite_util.c | 16 + .../nodes/composite/node_composite_util.h | 4 + .../composite/nodes/node_composite_blur.c | 22 +- .../composite/nodes/node_composite_dilate.c | 8 +- .../composite/nodes/node_composite_keying.c | 218 +++++ .../nodes/node_composite_keyingscreen.c | 202 +++++ 35 files changed, 2587 insertions(+), 13 deletions(-) create mode 100644 source/blender/blenlib/BLI_voronoi.h create mode 100644 source/blender/blenlib/intern/voronoi.c create mode 100644 source/blender/compositor/nodes/COM_KeyingNode.cpp create mode 100644 source/blender/compositor/nodes/COM_KeyingNode.h create mode 100644 source/blender/compositor/nodes/COM_KeyingScreenNode.cpp create mode 100644 source/blender/compositor/nodes/COM_KeyingScreenNode.h create mode 100644 source/blender/compositor/operations/COM_KeyingDispillOperation.cpp create mode 100644 source/blender/compositor/operations/COM_KeyingDispillOperation.h create mode 100644 source/blender/compositor/operations/COM_KeyingOperation.cpp create mode 100644 source/blender/compositor/operations/COM_KeyingOperation.h create mode 100644 source/blender/compositor/operations/COM_KeyingScreenOperation.cpp create mode 100644 source/blender/compositor/operations/COM_KeyingScreenOperation.h create mode 100644 source/blender/nodes/composite/nodes/node_composite_keying.c create mode 100644 source/blender/nodes/composite/nodes/node_composite_keyingscreen.c diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 7e925e545dc..fde6d93849d 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -655,6 +655,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat); #define CMP_NODE_DOUBLEEDGEMASK 266 #define CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED 267 /* DEPRECATED multi file node has been merged into regular CMP_NODE_OUTPUT_FILE */ #define CMP_NODE_MASK 268 +#define CMP_NODE_KEYINGSCREEN 269 +#define CMP_NODE_KEYING 270 #define CMP_NODE_GLARE 301 #define CMP_NODE_TONEMAP 302 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 54edd7064a1..35e838d94fa 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1926,6 +1926,8 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_color_spill(ttype); register_node_type_cmp_luma_matte(ttype); register_node_type_cmp_doubleedgemask(ttype); + register_node_type_cmp_keyingscreen(ttype); + register_node_type_cmp_keying(ttype); register_node_type_cmp_translate(ttype); register_node_type_cmp_rotate(ttype); diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 22672db9edb..b0e0d3cbf19 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -53,6 +53,9 @@ #ifndef M_SQRT1_2 #define M_SQRT1_2 0.70710678118654752440 #endif +#ifndef M_SQRT3 +#define M_SQRT3 1.7320508075688772 +#endif #ifndef M_1_PI #define M_1_PI 0.318309886183790671538 #endif diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 746a2b958ea..44f54c41129 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -69,6 +69,8 @@ void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv); void rgb_to_hsv_v(const float rgb[3], float r_hsv[3]); void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv); void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3]); +void rgb_to_lab(float r, float g, float b, float *ll, float *la, float *lb); +void rgb_to_xyz(float r, float g, float b, float *x, float *y, float *z); unsigned int rgb_to_cpack(float r, float g, float b); unsigned int hsv_to_cpack(float h, float s, float v); @@ -112,6 +114,8 @@ void rgba_uchar_to_float(float col_r[4], const unsigned char col_ub[4]); void rgb_float_to_uchar(unsigned char col_r[3], const float col_f[3]); void rgba_float_to_uchar(unsigned char col_r[4], const float col_f[4]); +void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b); + /***************** lift/gamma/gain / ASC-CDL conversion *****************/ void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power); diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 0560a3f6e64..93599dee63d 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -191,6 +191,9 @@ void barycentric_transform(float pt_tar[3], float const pt_src[3], void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]); +int barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]); +int barycentric_inside_triangle_v2(const float w[3]); + void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]); void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]); diff --git a/source/blender/blenlib/BLI_voronoi.h b/source/blender/blenlib/BLI_voronoi.h new file mode 100644 index 00000000000..a67b01c5175 --- /dev/null +++ b/source/blender/blenlib/BLI_voronoi.h @@ -0,0 +1,70 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_VORONOI_H__ +#define __BLI_VORONOI_H__ + +struct ListBase; + +/** \file BLI_voronoi.h + * \ingroup bli + */ + +typedef struct VoronoiSite { + float co[2]; + float color[3]; +} VoronoiSite; + +typedef struct VoronoiEdge { + struct VoronoiEdge *next, *prev; + + float start[2], end[2]; /* start and end points */ + + /* this fields are used during diagram computation only */ + + float direction[2]; /* directional vector, from "start", points to "end", normal of |left, right| */ + + float left[2]; /* point on Voronoi place on the left side of edge */ + float right[2]; /* point on Voronoi place on the right side of edge */ + + float f, g; /* directional coeffitients satisfying equation y = f*x + g (edge lies on this line) */ + + /* some edges consist of two parts, so we add the pointer to another part to connect them at the end of an algorithm */ + struct VoronoiEdge *neighbour; +} VoronoiEdge; + +typedef struct VoronoiTriangulationPoint { + float co[2]; + float color[3]; + int power; +} VoronoiTriangulationPoint; + +void BLI_voronoi_compute(const VoronoiSite *sites, int sites_total, int width, int height, struct ListBase *edges); + +void BLI_voronoi_triangulate(const VoronoiSite *sites, int sites_total, struct ListBase *edges, int width, int height, + VoronoiTriangulationPoint **triangulated_points_r, int *triangulated_points_total_r, + int (**triangles_r)[3], int *triangles_total_r); + +#endif /* __BLI_VORONOI_H__ */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index d535e190314..ac7681e3be7 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -89,6 +89,7 @@ set(SRC intern/time.c intern/uvproject.c intern/voxel.c + intern/voronoi.c intern/winstuff.c BLI_args.h diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 152fc98945f..9433cfd31df 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -264,6 +264,35 @@ void rgb_to_hsv_v(const float rgb[3], float r_hsv[3]) rgb_to_hsv(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]); } +void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll) +{ + float cmax = MAX3(r, g, b); + float cmin = MIN3(r, g, b); + float h, s, l = (cmax + cmin) / 2.0f; + + if (cmax == cmin) { + h = s = 0.0f; // achromatic + } + else { + float d = cmax - cmin; + s = l > 0.5f ? d / (2.0f - cmax - cmin) : d / (cmax + cmin); + if (cmax == r) { + h = (g - b) / d + (g < b ? 6.0f : 0.0f); + } + else if (cmax == g) { + h = (b - r) / d + 2.0f; + } + else { + h = (r - g) / d + 4.0f; + } + } + h /= 6.0f; + + *lh = h; + *ls = s; + *ll = l; +} + void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv) { float orig_h = *lh; @@ -603,3 +632,58 @@ void BLI_init_srgb_conversion(void) BLI_color_to_srgb_table[i] = b * 0x100; } } +static float inverse_srgb_companding(float v) +{ + if (v > 0.04045f) { + return powf((v + 0.055f) / 1.055f, 2.4); + } + else { + return v / 12.92f; + } +} + +void rgb_to_xyz(float r, float g, float b, float *x, float *y, float *z) +{ + r = inverse_srgb_companding(r) * 100.0f; + g = inverse_srgb_companding(g) * 100.0f; + b = inverse_srgb_companding(b) * 100.0f; + + *x = r * 0.4124 + g * 0.3576 + b * 0.1805; + *y = r * 0.2126 + g * 0.7152 + b * 0.0722; + *z = r * 0.0193 + g * 0.1192 + b * 0.9505; +} + +static float xyz_to_lab_component(float v) +{ + const float eps = 0.008856f; + const float k = 903.3f; + + if (v > eps) { + return pow(v, 1.0f / 3.0f); + } + else { + return (k * v + 16.0f) / 116.0f; + } +} + +void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b) +{ + float xr = x / 95.047f; + float yr = y / 100.0f; + float zr = z / 108.883f; + + float fx = xyz_to_lab_component(xr); + float fy = xyz_to_lab_component(yr); + float fz = xyz_to_lab_component(zr); + + *l = 116.0f * fy - 16.0f; + *a = 500.0f * (fx - fy); + *b = 200.0f * (fy - fz); +} + +void rgb_to_lab(float r, float g, float b, float *ll, float *la, float *lb) +{ + float x, y, z; + rgb_to_xyz(r, g, b, &x, &y, &z); + xyz_to_lab(x, y, z, ll, la, lb); +} diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 3962f53862d..d35624e84d2 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1825,6 +1825,45 @@ void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], co } } +/* return 1 of point is inside triangle, 2 if it's on the edge, 0 if point is outside of triangle */ +int barycentric_inside_triangle_v2(const float w[3]) +{ + if (IN_RANGE(w[0], 0.0f, 1.0f) && + IN_RANGE(w[1], 0.0f, 1.0f) && + IN_RANGE(w[2], 0.0f, 1.0f)) + { + return 1; + } + else if (IN_RANGE_INCL(w[0], 0.0f, 1.0f) && + IN_RANGE_INCL(w[1], 0.0f, 1.0f) && + IN_RANGE_INCL(w[2], 0.0f, 1.0f)) + { + return 2; + } + + return 0; +} + +/* returns 0 for degenerated triangles */ +int barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]) +{ + float x = co[0], y = co[1]; + float x1 = v1[0], y1 = v1[1]; + float x2 = v2[0], y2 = v2[1]; + float x3 = v3[0], y3 = v3[1]; + float det = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3); + + if (fabsf(det) > FLT_EPSILON) { + w[0] = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / det; + w[1] = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / det; + w[2] = 1.0f - w[0] - w[1]; + + return 1; + } + + return 0; +} + /* used by projection painting * note: using area_tri_signed_v2 means locations outside the triangle are correctly weighted */ void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]) diff --git a/source/blender/blenlib/intern/voronoi.c b/source/blender/blenlib/intern/voronoi.c new file mode 100644 index 00000000000..0088d24d741 --- /dev/null +++ b/source/blender/blenlib/intern/voronoi.c @@ -0,0 +1,833 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* + * Fortune's algorithm implemented using explanation and some code snippets from + * http://blog.ivank.net/fortunes-algorithm-and-implementation.html + */ + +/** \file blender/blenkernel/intern/tracking.c + * \ingroup bli + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_voronoi.h" +#include "BLI_utildefines.h" + +#define VORONOI_EPS 1e-3 + +enum { + voronoiEventType_Site = 0, + voronoiEventType_Circle = 1 +} voronoiEventType; + +typedef struct VoronoiEvent { + struct VoronoiEvent *next, *prev; + + int type; /* type of event (site or circle) */ + float site[2]; /* site for which event was generated */ + + struct VoronoiParabola *parabola; /* parabola for which event was generated */ +} VoronoiEvent; + +typedef struct VoronoiParabola { + struct VoronoiParabola *left, *right, *parent; + VoronoiEvent *event; + int is_leaf; + float site[2]; + VoronoiEdge *edge; +} VoronoiParabola; + +typedef struct VoronoiProcess { + ListBase queue, edges; + VoronoiParabola *root; + int width, height; + float current_y; +} VoronoiProcess; + +/* event */ + +static void voronoi_insertEvent(VoronoiProcess *process, VoronoiEvent *event) +{ + VoronoiEvent *current_event = process->queue.first; + + while (current_event) { + if (current_event->site[1] < event->site[1]) { + break; + } + if (current_event->site[1] == event->site[1]) { + event->site[1] -= VORONOI_EPS; + } + + current_event = current_event->next; + } + + BLI_insertlinkbefore(&process->queue, current_event, event); +} + +/* edge */ +static VoronoiEdge *voronoiEdge_new(float start[2], float left[2], float right[2]) +{ + VoronoiEdge *edge = MEM_callocN(sizeof(VoronoiEdge), "voronoi edge"); + + copy_v2_v2(edge->start, start); + copy_v2_v2(edge->left, left); + copy_v2_v2(edge->right, right); + + edge->neighbour = NULL; + edge->end[0] = 0; + edge->end[1] = 0; + + edge->f = (right[0] - left[0]) / (left[1] - right[1]); + edge->g = start[1] - edge->f * start[0]; + + edge->direction[0] = right[1] - left[1]; + edge->direction[1] = -(right[0] - left[0]); + + return edge; +} + +/* parabola */ + +static VoronoiParabola *voronoiParabola_new(void) +{ + VoronoiParabola *parabola = MEM_callocN(sizeof(VoronoiParabola), "voronoi parabola"); + + parabola->is_leaf = FALSE; + parabola->event = NULL; + parabola->edge = NULL; + parabola->parent = 0; + + return parabola; +} + +static VoronoiParabola *voronoiParabola_newSite(float site[2]) +{ + VoronoiParabola *parabola = MEM_callocN(sizeof(VoronoiParabola), "voronoi parabola site"); + + copy_v2_v2(parabola->site, site); + parabola->is_leaf = TRUE; + parabola->event = NULL; + parabola->edge = NULL; + parabola->parent = 0; + + return parabola; +} + +/* returns the closest leave which is on the left of current node */ +static VoronoiParabola *voronoiParabola_getLeftChild(VoronoiParabola *parabola) +{ + VoronoiParabola *current_parabola; + + if (!parabola) + return NULL; + + current_parabola = parabola->left; + while (!current_parabola->is_leaf) { + current_parabola = current_parabola->right; + } + + return current_parabola; +} + +/* returns the closest leave which is on the right of current node */ +static VoronoiParabola *voronoiParabola_getRightChild(VoronoiParabola *parabola) +{ + VoronoiParabola *current_parabola; + + if (!parabola) + return NULL; + + current_parabola = parabola->right; + while (!current_parabola->is_leaf) { + current_parabola = current_parabola->left; + } + + return current_parabola; +} + +/* returns the closest parent which is on the left */ +static VoronoiParabola *voronoiParabola_getLeftParent(VoronoiParabola *parabola) +{ + VoronoiParabola *current_par = parabola->parent; + VoronoiParabola *last_parabola = parabola; + + while (current_par->left == last_parabola) { + if (!current_par->parent) + return NULL; + + last_parabola = current_par; + current_par = current_par->parent; + } + + return current_par; +} + +/* returns the closest parent which is on the right */ +static VoronoiParabola *voronoiParabola_getRightParent(VoronoiParabola *parabola) +{ + VoronoiParabola *current_parabola = parabola->parent; + VoronoiParabola *last_parabola = parabola; + + while (current_parabola->right == last_parabola) { + if (!current_parabola->parent) + return NULL; + + last_parabola = current_parabola; + current_parabola = current_parabola->parent; + } + + return current_parabola; +} + +static void voronoiParabola_setLeft(VoronoiParabola *parabola, VoronoiParabola *left) +{ + parabola->left = left; + left->parent = parabola; +} + +static void voronoiParabola_setRight(VoronoiParabola *parabola, VoronoiParabola *right) +{ + parabola->right = right; + right->parent = parabola; +} + +static float voronoi_getY(VoronoiProcess *process, float p[2], float x) +{ + float ly = process->current_y; + + float dp = 2 * (p[1] - ly); + float a1 = 1 / dp; + float b1 = -2 * p[0] / dp; + float c1 = ly + dp / 4 + p[0] * p[0] / dp; + + return a1 * x * x + b1 * x + c1; +} + +static float voronoi_getXOfEdge(VoronoiProcess *process, VoronoiParabola *par, float y) +{ + VoronoiParabola *left = voronoiParabola_getLeftChild(par); + VoronoiParabola *right = voronoiParabola_getRightChild(par); + float p[2], r[2]; + float dp, a1, b1, c1, a2, b2, c2, a, b, c, disc, ry, x1, x2; + float ly = process->current_y; + + copy_v2_v2(p, left->site); + copy_v2_v2(r, right->site); + + dp = 2.0f * (p[1] - y); + a1 = 1.0f / dp; + b1 = -2.0f * p[0] / dp; + c1 = y + dp / 4 + p[0] * p[0] / dp; + + dp = 2.0f * (r[1] - y); + a2 = 1.0f / dp; + b2 = -2.0f * r[0] / dp; + c2 = ly + dp / 4 + r[0] * r[0] / dp; + + a = a1 - a2; + b = b1 - b2; + c = c1 - c2; + + disc = b*b - 4 * a * c; + x1 = (-b + sqrtf(disc)) / (2*a); + x2 = (-b - sqrtf(disc)) / (2*a); + + if (p[1] < r[1]) + ry = MAX2(x1, x2); + else + ry = MIN2(x1, x2); + + return ry; +} + +static VoronoiParabola *voronoi_getParabolaByX(VoronoiProcess *process, float xx) +{ + VoronoiParabola * par = process->root; + float x = 0.0f; + float ly = process->current_y; + + while (!par->is_leaf) { + x = voronoi_getXOfEdge(process, par, ly); + + if (x > xx) + par = par->left; + else + par = par->right; + } + + return par; +} + +static int voronoi_getEdgeIntersection(VoronoiEdge *a, VoronoiEdge *b, float p[2]) +{ + float x = (b->g - a->g) / (a->f - b->f); + float y = a->f * x + a->g; + + if ((x - a->start[0]) / a->direction[0] < 0) + return 0; + + if ((y - a->start[1]) / a->direction[1] < 0) + return 0; + + if ((x - b->start[0]) / b->direction[0] < 0) + return 0; + + if ((y - b->start[1]) / b->direction[1] < 0) + return 0; + + p[0] = x; + p[1] = y; + + return 1; +} + +static void voronoi_checkCircle(VoronoiProcess *process, VoronoiParabola *b) +{ + VoronoiParabola *lp = voronoiParabola_getLeftParent(b); + VoronoiParabola *rp = voronoiParabola_getRightParent(b); + + VoronoiParabola *a = voronoiParabola_getLeftChild(lp); + VoronoiParabola *c = voronoiParabola_getRightChild(rp); + + VoronoiEvent *event; + + float ly = process->current_y; + float s[2], dx, dy, d; + + if (!a || !c || len_squared_v2v2(a->site, c->site) < VORONOI_EPS) + return; + + if (!voronoi_getEdgeIntersection(lp->edge, rp->edge, s)) + return; + + dx = a->site[0] - s[0]; + dy = a->site[1] - s[1]; + + d = sqrtf((dx * dx) + (dy * dy)); + + if (s[1] - d >= ly) + return; + + event = MEM_callocN(sizeof(VoronoiEvent), "voronoi circle event"); + + event->type = voronoiEventType_Circle; + + event->site[0] = s[0]; + event->site[1] = s[1] - d; + + b->event = event; + event->parabola = b; + + voronoi_insertEvent(process, event); +} + +static void voronoi_addParabola(VoronoiProcess *process, float site[2]) +{ + VoronoiParabola *root = process->root; + VoronoiParabola *par, *p0, *p1, *p2; + VoronoiEdge *el, *er; + float start[2]; + + if (!process->root) { + process->root = voronoiParabola_newSite(site); + + return; + } + + if (root->is_leaf && root->site[1] - site[1] < 0) { + float *fp = root->site; + float s[2]; + + root->is_leaf = FALSE; + voronoiParabola_setLeft(root, voronoiParabola_newSite(fp)); + voronoiParabola_setRight(root, voronoiParabola_newSite(site)); + + s[0] = (site[0] + fp[0]) / 2.0f; + s[1] = process->height; + + if(site[0] > fp[0]) + root->edge = voronoiEdge_new(s, fp, site); + else + root->edge = voronoiEdge_new(s, site, fp); + + BLI_addtail(&process->edges, root->edge); + + return; + } + + par = voronoi_getParabolaByX(process, site[0]); + + if (par->event) { + BLI_freelinkN(&process->queue, par->event); + + par->event = NULL; + } + + start[0] = site[0]; + start[1] = voronoi_getY(process, par->site, site[0]); + + el = voronoiEdge_new(start, par->site, site); + er = voronoiEdge_new(start, site, par->site); + + el->neighbour = er; + BLI_addtail(&process->edges, el); + + par->edge = er; + par->is_leaf = FALSE; + + p0 = voronoiParabola_newSite(par->site); + p1 = voronoiParabola_newSite(site); + p2 = voronoiParabola_newSite(par->site); + + voronoiParabola_setRight(par, p2); + voronoiParabola_setLeft(par, voronoiParabola_new()); + par->left->edge = el; + + voronoiParabola_setLeft(par->left, p0); + voronoiParabola_setRight(par->left, p1); + + voronoi_checkCircle(process, p0); + voronoi_checkCircle(process, p2); +} + +static void voronoi_removeParabola(VoronoiProcess *process, VoronoiEvent *event) +{ + VoronoiParabola *p1 = event->parabola; + + VoronoiParabola *xl = voronoiParabola_getLeftParent(p1); + VoronoiParabola *xr = voronoiParabola_getRightParent(p1); + + VoronoiParabola *p0 = voronoiParabola_getLeftChild(xl); + VoronoiParabola *p2 = voronoiParabola_getRightChild(xr); + + VoronoiParabola *higher = NULL, *par, *gparent; + + float p[2]; + + if (p0->event) { + BLI_freelinkN(&process->queue, p0->event); + p0->event = NULL; + } + + if (p2->event) { + BLI_freelinkN(&process->queue, p2->event); + p2->event = NULL; + } + + p[0] = event->site[0]; + p[1] = voronoi_getY(process, p1->site, event->site[0]); + + copy_v2_v2(xl->edge->end, p); + copy_v2_v2(xr->edge->end, p); + + par = p1; + while (par != process->root) { + par = par->parent; + + if (par == xl) + higher = xl; + if (par == xr) + higher = xr; + } + + higher->edge = voronoiEdge_new(p, p0->site, p2->site); + BLI_addtail(&process->edges, higher->edge); + + gparent = p1->parent->parent; + if (p1->parent->left == p1) { + if (gparent->left == p1->parent) + voronoiParabola_setLeft(gparent, p1->parent->right); + if (gparent->right == p1->parent) + voronoiParabola_setRight(gparent, p1->parent->right); + } + else { + if (gparent->left == p1->parent) + voronoiParabola_setLeft(gparent, p1->parent->left); + if (gparent->right == p1->parent) + voronoiParabola_setRight(gparent, p1->parent->left); + } + + MEM_freeN(p1->parent); + MEM_freeN(p1); + + voronoi_checkCircle(process, p0); + voronoi_checkCircle(process, p2); +} + +void voronoi_finishEdge(VoronoiProcess *process, VoronoiParabola *parabola) +{ + float mx; + + if (parabola->is_leaf) { + MEM_freeN(parabola); + return; + } + + if (parabola->edge->direction[0] > 0.0f) + mx = MAX2(process->width, parabola->edge->start[0] + 10); + else + mx = MIN2(0.0, parabola->edge->start[0] - 10); + + parabola->edge->end[0] = mx; + parabola->edge->end[1] = mx * parabola->edge->f + parabola->edge->g; + + voronoi_finishEdge(process, parabola->left); + voronoi_finishEdge(process, parabola->right); + + MEM_freeN(parabola); +} + +void voronoi_clampEdgeVertex(int width, int height, float *coord, float *other_coord) +{ + const float corners[4][2] = {{0.0f, 0.0f}, + {width - 1, 0.0f}, + {width - 1, height - 1}, + {0.0f, height - 1}}; + int i; + + if (IN_RANGE_INCL(coord[0], 0, width-1) && IN_RANGE_INCL(coord[1], 0, height-1)) { + return; + } + + for (i = 0; i < 4; i++) { + float v1[2], v2[2]; + float p[2]; + + copy_v2_v2(v1, corners[i]); + + if (i == 3) + copy_v2_v2(v2, corners[0]); + else + copy_v2_v2(v2, corners[i + 1]); + + if (isect_seg_seg_v2_point(v1, v2, coord, other_coord, p) == 1) { + if (i == 0 && coord[1] > p[1]) + continue; + if (i == 1 && coord[0] < p[0]) + continue; + if (i == 2 && coord[1] < p[1]) + continue; + if (i == 3 && coord[0] > p[0]) + continue; + + copy_v2_v2(coord, p); + } + } +} + +void voronoi_clampEdges(ListBase *edges, int width, int height, ListBase *clamped_edges) +{ + VoronoiEdge *edge; + + edge = edges->first; + while (edge) { + VoronoiEdge *new_edge = MEM_callocN(sizeof(VoronoiEdge), "clamped edge"); + + *new_edge = *edge; + BLI_addtail(clamped_edges, new_edge); + + voronoi_clampEdgeVertex(width, height, new_edge->start, new_edge->end); + voronoi_clampEdgeVertex(width, height, new_edge->end, new_edge->start); + + edge = edge->next; + } +} + +static int voronoi_getNextSideCoord(ListBase *edges, float coord[2], int dim, int dir, float next_coord[2]) +{ + VoronoiEdge *edge = edges->first; + float distance = FLT_MAX; + int other_dim = dim ? 0 : 1; + + while (edge) { + int ok = FALSE; + float co[2], cur_distance; + + if (fabsf(edge->start[other_dim] - coord[other_dim]) < VORONOI_EPS && + len_squared_v2v2(coord, edge->start) > VORONOI_EPS) + { + copy_v2_v2(co, edge->start); + ok = TRUE; + } + + if (fabsf(edge->end[other_dim] - coord[other_dim]) < VORONOI_EPS && + len_squared_v2v2(coord, edge->end) > VORONOI_EPS) + { + copy_v2_v2(co, edge->end); + ok = TRUE; + } + + if (ok) { + if (dir > 0 && coord[dim] > co[dim]) { + ok = FALSE; + } + else if (dir < 0 && coord[dim] < co[dim]) { + ok = FALSE; + } + } + + if (ok) { + cur_distance = len_squared_v2v2(coord, co); + if (cur_distance < distance) { + copy_v2_v2(next_coord, co); + distance = cur_distance; + } + } + + edge = edge->next; + } + + return distance < FLT_MAX; +} + +static void voronoi_createBoundaryEdges(ListBase *edges, int width, int height) +{ + const float corners[4][2] = {{width - 1, 0.0f}, + {width - 1, height - 1}, + {0.0f, height - 1}, + {0.0f, 0.0f}}; + int i, dim = 0, dir = 1; + + float coord[2] = {0.0f, 0.0f}; + float next_coord[2] = {0.0f, 0.0f}; + + for (i = 0; i < 4; i++) { + while (voronoi_getNextSideCoord(edges, coord, dim, dir, next_coord)) { + VoronoiEdge *edge = MEM_callocN(sizeof(VoronoiEdge), "boundary edge"); + + copy_v2_v2(edge->start, coord); + copy_v2_v2(edge->end, next_coord); + BLI_addtail(edges, edge); + + copy_v2_v2(coord, next_coord); + } + + if (len_squared_v2v2(coord, corners[i]) > VORONOI_EPS) { + VoronoiEdge *edge = MEM_callocN(sizeof(VoronoiEdge), "boundary edge"); + + copy_v2_v2(edge->start, coord); + copy_v2_v2(edge->end, corners[i]); + BLI_addtail(edges, edge); + copy_v2_v2(coord, corners[i]); + } + + dim = dim ? 0 : 1; + if (i == 1) + dir = -1; + } +} + +void BLI_voronoi_compute(const VoronoiSite *sites, int sites_total, int width, int height, ListBase *edges) +{ + VoronoiProcess process; + VoronoiEdge *edge; + int i; + + memset(&process, 0, sizeof(VoronoiProcess)); + + process.width = width; + process.height = height; + + for (i = 0; i < sites_total; i++) { + VoronoiEvent *event = MEM_callocN(sizeof(VoronoiEvent), "voronoi site event"); + + event->type = voronoiEventType_Site; + copy_v2_v2(event->site, sites[i].co); + + voronoi_insertEvent(&process, event); + } + + while (process.queue.first) { + VoronoiEvent *event = process.queue.first; + + process.current_y = event->site[1]; + + if (event->type == voronoiEventType_Site) { + voronoi_addParabola(&process, event->site); + } + else { + voronoi_removeParabola(&process, event); + } + + BLI_freelinkN(&process.queue, event); + } + + voronoi_finishEdge(&process, process.root); + + edge = process.edges.first; + while (edge) { + if (edge->neighbour) { + copy_v2_v2(edge->start, edge->neighbour->end); + MEM_freeN(edge->neighbour); + } + + edge = edge->next; + } + + BLI_movelisttolist(edges, &process.edges); +} + +static int testVoronoiEdge(const float site[2], const float point[2], const VoronoiEdge *edge) +{ + float p[2]; + + if (isect_seg_seg_v2_point(site, point, edge->start, edge->end, p) == 1) { + if (len_squared_v2v2(p, edge->start) > VORONOI_EPS && + len_squared_v2v2(p, edge->end) > VORONOI_EPS) + { + return FALSE; + } + } + + return TRUE; +} + +static int voronoi_addTriangulationPoint(const float coord[2], const float color[3], + VoronoiTriangulationPoint **triangulated_points, + int *triangulated_points_total) +{ + VoronoiTriangulationPoint *triangulation_point; + int i; + + for (i = 0; i < *triangulated_points_total; i++) { + if (equals_v2v2(coord, (*triangulated_points)[i].co)) { + triangulation_point = &(*triangulated_points)[i]; + + add_v3_v3(triangulation_point->color, color); + triangulation_point->power++; + + return i; + } + } + + if (*triangulated_points) { + *triangulated_points = MEM_reallocN(*triangulated_points, + sizeof(VoronoiTriangulationPoint) * (*triangulated_points_total + 1)); + } + else { + *triangulated_points = MEM_callocN(sizeof(VoronoiTriangulationPoint), "triangulation points"); + } + + triangulation_point = &(*triangulated_points)[(*triangulated_points_total)]; + copy_v2_v2(triangulation_point->co, coord); + copy_v3_v3(triangulation_point->color, color); + + triangulation_point->power = 1; + + (*triangulated_points_total)++; + + return (*triangulated_points_total) - 1; +} + +static void voronoi_addTriangle(int v1, int v2, int v3, int (**triangles)[3], int *triangles_total) +{ + int *triangle; + + if (*triangles) { + *triangles = MEM_reallocN(*triangles, sizeof(int[3]) * (*triangles_total + 1)); + } + else { + *triangles = MEM_callocN(sizeof(int[3]), "trianglulation triangles"); + } + + triangle = (int*)&(*triangles)[(*triangles_total)]; + + triangle[0] = v1; + triangle[1] = v2; + triangle[2] = v3; + + (*triangles_total)++; +} + +void BLI_voronoi_triangulate(const VoronoiSite *sites, int sites_total, ListBase *edges, int width, int height, + VoronoiTriangulationPoint **triangulated_points_r, int *triangulated_points_total_r, + int (**triangles_r)[3], int *triangles_total_r) +{ + VoronoiTriangulationPoint *triangulated_points = NULL; + int (*triangles)[3] = NULL; + int triangulated_points_total = 0, triangles_total = 0; + int i; + ListBase boundary_edges = {NULL, NULL}; + + voronoi_clampEdges(edges, width, height, &boundary_edges); + voronoi_createBoundaryEdges(&boundary_edges, width, height); + + for (i = 0; i < sites_total; i++) { + VoronoiEdge *edge; + int v1; + + v1 = voronoi_addTriangulationPoint(sites[i].co, sites[i].color, &triangulated_points, &triangulated_points_total); + + edge = boundary_edges.first; + while (edge) { + VoronoiEdge *test_edge = boundary_edges.first; + int ok_start = TRUE, ok_end = TRUE; + + while (test_edge) { + float v1[2], v2[2]; + + sub_v2_v2v2(v1, edge->start, sites[i].co); + sub_v2_v2v2(v2, edge->end, sites[i].co); + + if (ok_start && !testVoronoiEdge(sites[i].co, edge->start, test_edge)) + ok_start = FALSE; + + if (ok_end && !testVoronoiEdge(sites[i].co, edge->end, test_edge)) + ok_end = FALSE; + + test_edge = test_edge->next; + } + + if (ok_start && ok_end) { + int v2, v3; + + v2 = voronoi_addTriangulationPoint(edge->start, sites[i].color, &triangulated_points, &triangulated_points_total); + v3 = voronoi_addTriangulationPoint(edge->end, sites[i].color, &triangulated_points, &triangulated_points_total); + + voronoi_addTriangle(v1, v2, v3, &triangles, &triangles_total); + } + + edge = edge->next; + } + } + + for (i = 0; i < triangulated_points_total; i++) { + VoronoiTriangulationPoint *triangulation_point = &triangulated_points[i]; + + mul_v3_fl(triangulation_point->color, 1.0f / triangulation_point->power); + } + + *triangulated_points_r = triangulated_points; + *triangulated_points_total_r = triangulated_points_total; + + *triangles_r = triangles; + *triangles_total_r = triangles_total; + + BLI_freelistN(&boundary_edges); +} diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 5e778d4d03b..d4e083f9ec1 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -331,6 +331,18 @@ set(SRC operations/COM_DoubleEdgeMaskOperation.cpp operations/COM_DoubleEdgeMaskOperation.h + + nodes/COM_KeyingNode.cpp + nodes/COM_KeyingNode.h + nodes/COM_KeyingScreenNode.cpp + nodes/COM_KeyingScreenNode.h + operations/COM_KeyingOperation.cpp + operations/COM_KeyingOperation.h + operations/COM_KeyingScreenOperation.cpp + operations/COM_KeyingScreenOperation.h + operations/COM_KeyingDispillOperation.cpp + operations/COM_KeyingDispillOperation.h + operations/COM_ColorSpillOperation.cpp operations/COM_ColorSpillOperation.h operations/COM_RenderLayersBaseProg.cpp diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index dc6409e7b86..747d6495f5d 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -112,6 +112,8 @@ #include "COM_DoubleEdgeMaskNode.h" #include "COM_CropNode.h" #include "COM_MaskNode.h" +#include "COM_KeyingScreenNode.h" +#include "COM_KeyingNode.h" Node *Converter::convert(bNode *bNode) { @@ -350,6 +352,11 @@ case CMP_NODE_OUTPUT_FILE: break; case CMP_NODE_MASK: node = new MaskNode(bNode); + case CMP_NODE_KEYINGSCREEN: + node = new KeyingScreenNode(bNode); + break; + case CMP_NODE_KEYING: + node = new KeyingNode(bNode); break; /* not inplemented yet */ default: diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp new file mode 100644 index 00000000000..725060371a1 --- /dev/null +++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp @@ -0,0 +1,211 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_KeyingNode.h" + +#include "COM_ExecutionSystem.h" + +#include "COM_KeyingOperation.h" +#include "COM_KeyingDispillOperation.h" + +#include "COM_SeparateChannelOperation.h" +#include "COM_CombineChannelsOperation.h" +#include "COM_ConvertRGBToYCCOperation.h" +#include "COM_ConvertYCCToRGBOperation.h" +#include "COM_FastGaussianBlurOperation.h" +#include "COM_SetValueOperation.h" + +#include "COM_DilateErodeOperation.h" + +#include "COM_SetAlphaOperation.h" + +KeyingNode::KeyingNode(bNode *editorNode): Node(editorNode) +{ +} + +OutputSocket *KeyingNode::setupPreBlur(ExecutionSystem *graph, InputSocket *inputImage, int size, OutputSocket **originalImage) +{ + memset(&preBlurData, 0, sizeof(preBlurData)); + preBlurData.sizex = size; + preBlurData.sizey = size; + + ConvertRGBToYCCOperation *convertRGBToYCCOperation = new ConvertRGBToYCCOperation(); + convertRGBToYCCOperation->setMode(0); /* ITU 601 */ + + inputImage->relinkConnections(convertRGBToYCCOperation->getInputSocket(0), 0, graph); + graph->addOperation(convertRGBToYCCOperation); + + CombineChannelsOperation *combineOperation = new CombineChannelsOperation(); + graph->addOperation(combineOperation); + + for (int channel = 0; channel < 4; channel++) { + SeparateChannelOperation *separateOperation = new SeparateChannelOperation(); + separateOperation->setChannel(channel); + addLink(graph, convertRGBToYCCOperation->getOutputSocket(0), separateOperation->getInputSocket(0)); + graph->addOperation(separateOperation); + + if (channel == 0 || channel == 3) { + addLink(graph, separateOperation->getOutputSocket(0), combineOperation->getInputSocket(channel)); + } + else { + SetValueOperation *setValueOperation = new SetValueOperation(); + setValueOperation->setValue(1.0f); + graph->addOperation(setValueOperation); + + FastGaussianBlurOperation *blurOperation = new FastGaussianBlurOperation(); + blurOperation->setData(&preBlurData); + + addLink(graph, separateOperation->getOutputSocket(0), blurOperation->getInputSocket(0)); + addLink(graph, setValueOperation->getOutputSocket(0), blurOperation->getInputSocket(1)); + addLink(graph, blurOperation->getOutputSocket(0), combineOperation->getInputSocket(channel)); + graph->addOperation(blurOperation); + } + } + + ConvertYCCToRGBOperation *convertYCCToRGBOperation = new ConvertYCCToRGBOperation(); + convertYCCToRGBOperation->setMode(0); /* ITU 601 */ + addLink(graph, combineOperation->getOutputSocket(0), convertYCCToRGBOperation->getInputSocket(0)); + graph->addOperation(convertYCCToRGBOperation); + + *originalImage = convertRGBToYCCOperation->getInputSocket(0)->getConnection()->getFromSocket(); + + return convertYCCToRGBOperation->getOutputSocket(0); +} + +OutputSocket *KeyingNode::setupPostBlur(ExecutionSystem *graph, OutputSocket *postBLurInput, int size) +{ + memset(&postBlurData, 0, sizeof(postBlurData)); + + postBlurData.sizex = size; + postBlurData.sizey = size; + + SetValueOperation *setValueOperation = new SetValueOperation(); + + setValueOperation->setValue(1.0f); + graph->addOperation(setValueOperation); + + FastGaussianBlurOperation *blurOperation = new FastGaussianBlurOperation(); + blurOperation->setData(&postBlurData); + + addLink(graph, postBLurInput, blurOperation->getInputSocket(0)); + addLink(graph, setValueOperation->getOutputSocket(0), blurOperation->getInputSocket(1)); + + graph->addOperation(blurOperation); + + return blurOperation->getOutputSocket(); +} + +OutputSocket *KeyingNode::setupDilateErode(ExecutionSystem *graph, OutputSocket *dilateErodeInput, int distance) +{ + DilateStepOperation *dilateErodeOperation; + + if (distance > 0) { + dilateErodeOperation = new DilateStepOperation(); + dilateErodeOperation->setIterations(distance); + } + else { + dilateErodeOperation = new ErodeStepOperation(); + dilateErodeOperation->setIterations(-distance); + } + + addLink(graph, dilateErodeInput, dilateErodeOperation->getInputSocket(0)); + + graph->addOperation(dilateErodeOperation); + + return dilateErodeOperation->getOutputSocket(0); +} + +OutputSocket *KeyingNode::setupDispill(ExecutionSystem *graph, OutputSocket *dispillInput, InputSocket *inputScreen, float factor) +{ + KeyingDispillOperation *dispillOperation = new KeyingDispillOperation(); + + dispillOperation->setDispillFactor(factor); + + addLink(graph, dispillInput, dispillOperation->getInputSocket(0)); + inputScreen->relinkConnections(dispillOperation->getInputSocket(1), 1, graph); + + graph->addOperation(dispillOperation); + + return dispillOperation->getOutputSocket(0); +} + +void KeyingNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) +{ + InputSocket *inputImage = this->getInputSocket(0); + InputSocket *inputScreen = this->getInputSocket(1); + OutputSocket *outputImage = this->getOutputSocket(0); + OutputSocket *outputMatte = this->getOutputSocket(1); + OutputSocket *postprocessedMatte, *postprocessedImage, *originalImage; + + bNode *editorNode = this->getbNode(); + NodeKeyingData *keying_data = (NodeKeyingData *) editorNode->storage; + + /* keying operation */ + KeyingOperation *keyingOperation = new KeyingOperation(); + + keyingOperation->setClipBlack(keying_data->clip_black); + keyingOperation->setClipWhite(keying_data->clip_white); + + inputScreen->relinkConnections(keyingOperation->getInputSocket(1), 1, graph); + + if (keying_data->blur_pre) { + /* chroma preblur operation for input of keying operation */ + OutputSocket *preBluredImage = setupPreBlur(graph, inputImage, keying_data->blur_pre, &originalImage); + addLink(graph, preBluredImage, keyingOperation->getInputSocket(0)); + } + else { + inputImage->relinkConnections(keyingOperation->getInputSocket(0), 0, graph); + originalImage = keyingOperation->getInputSocket(0)->getConnection()->getFromSocket(); + } + + graph->addOperation(keyingOperation); + + /* apply blur on matte if needed */ + if (keying_data->blur_post) + postprocessedMatte = setupPostBlur(graph, keyingOperation->getOutputSocket(), keying_data->blur_post); + else + postprocessedMatte = keyingOperation->getOutputSocket(); + + /* matte dilate/erode */ + if (keying_data->dilate_distance != 0) { + postprocessedMatte = setupDilateErode(graph, postprocessedMatte, keying_data->dilate_distance); + } + + /* set alpha channel to output image */ + SetAlphaOperation *alphaOperation = new SetAlphaOperation(); + addLink(graph, originalImage, alphaOperation->getInputSocket(0)); + addLink(graph, postprocessedMatte, alphaOperation->getInputSocket(1)); + + postprocessedImage = alphaOperation->getOutputSocket(); + + /* dispill output image */ + if (keying_data->dispill_factor > 0.0f) { + postprocessedImage = setupDispill(graph, postprocessedImage, inputScreen, keying_data->dispill_factor); + } + + /* connect result to output sockets */ + outputImage->relinkConnections(postprocessedImage); + outputMatte->relinkConnections(postprocessedMatte); + + graph->addOperation(alphaOperation); +} diff --git a/source/blender/compositor/nodes/COM_KeyingNode.h b/source/blender/compositor/nodes/COM_KeyingNode.h new file mode 100644 index 00000000000..8c1ee8fdf72 --- /dev/null +++ b/source/blender/compositor/nodes/COM_KeyingNode.h @@ -0,0 +1,44 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_Node.h" +#include "DNA_node_types.h" + +/** + * @brief KeyingNode + * @ingroup Node + */ +class KeyingNode : public Node { +protected: + NodeBlurData preBlurData; + NodeBlurData postBlurData; + + OutputSocket *setupPreBlur(ExecutionSystem *graph, InputSocket *inputImage, int size, OutputSocket **originalImage); + OutputSocket *setupPostBlur(ExecutionSystem *graph, OutputSocket *postBLurInput, int size); + OutputSocket *setupDilateErode(ExecutionSystem *graph, OutputSocket *dilateErodeInput, int distance); + OutputSocket *setupDispill(ExecutionSystem *graph, OutputSocket *dispillInput, InputSocket *inputSrceen, float factor); +public: + KeyingNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); + +}; diff --git a/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp b/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp new file mode 100644 index 00000000000..ad58adae48b --- /dev/null +++ b/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_KeyingScreenNode.h" +#include "COM_ExecutionSystem.h" +#include "COM_KeyingScreenOperation.h" + +extern "C" { + #include "DNA_movieclip_types.h" +} + +KeyingScreenNode::KeyingScreenNode(bNode *editorNode): Node(editorNode) +{ +} + +void KeyingScreenNode::convertToOperations(ExecutionSystem *graph, CompositorContext * context) +{ + OutputSocket *outputScreen = this->getOutputSocket(0); + + bNode *editorNode = this->getbNode(); + MovieClip *clip = (MovieClip *) editorNode->id; + + NodeKeyingScreenData *keyingscreen_data = (NodeKeyingScreenData *) editorNode->storage; + + // always connect the output image + KeyingScreenOperation *operation = new KeyingScreenOperation(); + + if (outputScreen->isConnected()) { + outputScreen->relinkConnections(operation->getOutputSocket()); + } + + operation->setMovieClip(clip); + operation->setTrackingObject(keyingscreen_data->tracking_object); + operation->setFramenumber(context->getFramenumber()); + + graph->addOperation(operation); +} diff --git a/source/blender/compositor/nodes/COM_KeyingScreenNode.h b/source/blender/compositor/nodes/COM_KeyingScreenNode.h new file mode 100644 index 00000000000..7c87219ef6e --- /dev/null +++ b/source/blender/compositor/nodes/COM_KeyingScreenNode.h @@ -0,0 +1,36 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_Node.h" +#include "DNA_node_types.h" + +/** + * @brief KeyingScreenNode + * @ingroup Node + */ +class KeyingScreenNode : public Node { +public: + KeyingScreenNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); + +}; diff --git a/source/blender/compositor/operations/COM_KeyingDispillOperation.cpp b/source/blender/compositor/operations/COM_KeyingDispillOperation.cpp new file mode 100644 index 00000000000..5f4eaf3148d --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingDispillOperation.cpp @@ -0,0 +1,89 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_KeyingDispillOperation.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" + +static int get_pixel_primary_channel(float *pixel) +{ + float max_value = MAX3(pixel[0], pixel[1], pixel[2]); + + if (max_value == pixel[0]) + return 0; + else if (max_value == pixel[1]) + return 1; + + return 2; +} + +KeyingDispillOperation::KeyingDispillOperation(): NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + + this->dispillFactor = 0.5f; + + this->pixelReader = NULL; + this->screenReader = NULL; +} + +void KeyingDispillOperation::initExecution() +{ + this->pixelReader = this->getInputSocketReader(0); + this->screenReader = this->getInputSocketReader(1); +} + +void KeyingDispillOperation::deinitExecution() +{ + this->pixelReader = NULL; + this->screenReader = NULL; +} + +void KeyingDispillOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) +{ + float pixelColor[4]; + float screenColor[4]; + + this->pixelReader->read(pixelColor, x, y, sampler, inputBuffers); + this->screenReader->read(screenColor, x, y, sampler, inputBuffers); + + int screen_primary_channel = get_pixel_primary_channel(screenColor); + float average_value, amount; + + average_value = (pixelColor[0] + pixelColor[1] + pixelColor[2] - pixelColor[screen_primary_channel]) / 2.0f; + amount = pixelColor[screen_primary_channel] - average_value; + + color[0] = pixelColor[0]; + color[1] = pixelColor[1]; + color[2] = pixelColor[2]; + color[3] = pixelColor[3]; + + if (this->dispillFactor * amount > 0) { + color[screen_primary_channel] = pixelColor[screen_primary_channel] - this->dispillFactor * amount; + } +} diff --git a/source/blender/compositor/operations/COM_KeyingDispillOperation.h b/source/blender/compositor/operations/COM_KeyingDispillOperation.h new file mode 100644 index 00000000000..a918a918381 --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingDispillOperation.h @@ -0,0 +1,49 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#ifndef _COM_KeyingDispillOperation_h +#define _COM_KeyingDispillOperation_h + +#include "COM_NodeOperation.h" + +/** + * Class with implementation of keying dispill node + */ +class KeyingDispillOperation : public NodeOperation { +protected: + SocketReader *pixelReader; + SocketReader *screenReader; + float dispillFactor; + +public: + KeyingDispillOperation(); + + void initExecution(); + void deinitExecution(); + + void setDispillFactor(float value) {this->dispillFactor = value;} + + void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp new file mode 100644 index 00000000000..43348568a5d --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp @@ -0,0 +1,114 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_KeyingOperation.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" + +static int get_pixel_primary_channel(float *pixel) +{ + float max_value = MAX3(pixel[0], pixel[1], pixel[2]); + + if (max_value == pixel[0]) + return 0; + else if (max_value == pixel[1]) + return 1; + + return 2; +} + +static float get_pixel_saturation(float *pixel, float screen_balance) +{ + float min = MIN3(pixel[0], pixel[1], pixel[2]); + float max = MAX3(pixel[0], pixel[1], pixel[2]); + float mid = pixel[0] + pixel[1] + pixel[2] - min - max; + float val = (1.0f - screen_balance) * min + screen_balance * mid; + + return max - val; +} + +KeyingOperation::KeyingOperation(): NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VALUE); + + this->screenBalance = 0.5f; + this->clipBlack = 0.0f; + this->clipWhite = 1.0f; + + this->pixelReader = NULL; + this->screenReader = NULL; +} + +void KeyingOperation::initExecution() +{ + this->pixelReader = this->getInputSocketReader(0); + this->screenReader = this->getInputSocketReader(1); +} + +void KeyingOperation::deinitExecution() +{ + this->pixelReader = NULL; + this->screenReader = NULL; +} + +void KeyingOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) +{ + float pixelColor[4]; + float screenColor[4]; + + this->pixelReader->read(pixelColor, x, y, sampler, inputBuffers); + this->screenReader->read(screenColor, x, y, sampler, inputBuffers); + + float saturation = get_pixel_saturation(pixelColor, this->screenBalance); + float screen_saturation = get_pixel_saturation(screenColor, this->screenBalance); + int primary_channel = get_pixel_primary_channel(pixelColor); + int screen_primary_channel = get_pixel_primary_channel(screenColor); + + if (primary_channel != screen_primary_channel) { + /* different main channel means pixel is on foreground */ + color[0] = 1.0f; + } + else if (saturation >= screen_saturation) { + /* saturation of main channel is more than screen, definitely a background */ + color[0] = 0.0f; + } + else { + float distance; + + distance = 1.0f - saturation / screen_saturation; + + color[0] = distance; + + if (color[0] < this->clipBlack) + color[0] = 0.0f; + else if (color[0] >= this->clipWhite) + color[0] = 1.0f; + else + color[0] = (color[0] - this->clipBlack) / (this->clipWhite - this->clipBlack); + } +} diff --git a/source/blender/compositor/operations/COM_KeyingOperation.h b/source/blender/compositor/operations/COM_KeyingOperation.h new file mode 100644 index 00000000000..546ff355573 --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingOperation.h @@ -0,0 +1,57 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + + +#ifndef _COM_KeyingOperation_h +#define _COM_KeyingOperation_h + +#include + +#include "COM_NodeOperation.h" + +#include "BLI_listbase.h" + +/** + * Class with implementation of keying node + */ +class KeyingOperation : public NodeOperation { +protected: + SocketReader *pixelReader; + SocketReader *screenReader; + float screenBalance; + float clipBlack; + float clipWhite; + +public: + KeyingOperation(); + + void initExecution(); + void deinitExecution(); + + void setClipBlack(float value) {this->clipBlack = value;} + void setClipWhite(float value) {this->clipWhite = value;} + + void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp new file mode 100644 index 00000000000..456ab31db24 --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -0,0 +1,217 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_KeyingScreenOperation.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_math_color.h" + +#include "DNA_scene_types.h" + +extern "C" { + #include "BKE_movieclip.h" + #include "BKE_tracking.h" + + #include "IMB_imbuf.h" + #include "IMB_imbuf_types.h" +} + +KeyingScreenOperation::KeyingScreenOperation(): NodeOperation() +{ + this->addOutputSocket(COM_DT_COLOR); + this->movieClip = NULL; + this->framenumber = 0; + this->trackingObject[0] = 0; + setComplex(true); +} + +void KeyingScreenOperation::initExecution() +{ + initMutex(); + this->cachedTriangulation = NULL; +} + +void KeyingScreenOperation::deinitExecution() +{ + if (this->cachedTriangulation) { + TriangulationData *triangulation = cachedTriangulation; + + if (triangulation->triangulated_points) + MEM_freeN(triangulation->triangulated_points); + + if (triangulation->triangles) + MEM_freeN(triangulation->triangles); + + MEM_freeN(this->cachedTriangulation); + + this->cachedTriangulation = NULL; + } +} + +KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTriangulation() +{ + MovieClipUser user = {0}; + TriangulationData *triangulation; + MovieTracking *tracking = &movieClip->tracking; + MovieTrackingTrack *track; + VoronoiSite *sites; + ImBuf *ibuf; + ListBase *tracksbase; + ListBase edges = {NULL, NULL}; + int sites_total; + int i; + int width = this->getWidth(); + int height = this->getHeight(); + + if (this->trackingObject[0]) { + MovieTrackingObject *object = BKE_tracking_named_object(tracking, this->trackingObject); + + if (!object) + return NULL; + + tracksbase = BKE_tracking_object_tracks(tracking, object); + } + else + tracksbase = BKE_tracking_get_tracks(tracking); + + sites_total = BLI_countlist(tracksbase); + + if (!sites_total) + return NULL; + + triangulation = (TriangulationData *) MEM_callocN(sizeof(TriangulationData), "keying screen triangulation data"); + + BKE_movieclip_user_set_frame(&user, framenumber); + ibuf = BKE_movieclip_get_ibuf(movieClip, &user); + + sites = (VoronoiSite *) MEM_callocN(sizeof(VoronoiSite) * sites_total, "keyingscreen voronoi sites"); + track = (MovieTrackingTrack *) tracksbase->first; + i = 0; + while (track) { + VoronoiSite *site = &sites[i]; + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenumber); + ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, 0, TRUE, NULL, NULL); + int j; + + zero_v3(site->color); + for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { + if (pattern_ibuf->rect_float) { + add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); + } + else { + unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; + + site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); + site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); + site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + } + } + + mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); + IMB_freeImBuf(pattern_ibuf); + + site->co[0] = marker->pos[0] * width; + site->co[1] = marker->pos[1] * height; + + track = track->next; + i++; + } + + IMB_freeImBuf(ibuf); + + BLI_voronoi_compute(sites, sites_total, width, height, &edges); + + BLI_voronoi_triangulate(sites, sites_total, &edges, width, height, + &triangulation->triangulated_points, &triangulation->triangulated_points_total, + &triangulation->triangles, &triangulation->triangles_total); + + MEM_freeN(sites); + BLI_freelistN(&edges); + + return triangulation; +} + +void *KeyingScreenOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) +{ + if (this->movieClip == NULL) + return NULL; + + if (this->cachedTriangulation) + return this->cachedTriangulation; + + BLI_mutex_lock(getMutex()); + if (this->cachedTriangulation == NULL) { + this->cachedTriangulation = buildVoronoiTriangulation(); + } + BLI_mutex_unlock(getMutex()); + + return this->cachedTriangulation; +} + +void KeyingScreenOperation::determineResolution(unsigned int resolution[], unsigned int preferredResolution[]) +{ + resolution[0] = 0; + resolution[1] = 0; + + if (this->movieClip) { + MovieClipUser user = {0}; + int width, height; + + BKE_movieclip_user_set_frame(&user, framenumber); + BKE_movieclip_get_size(this->movieClip, &user, &width, &height); + + resolution[0] = width; + resolution[1] = height; + } +} + +void KeyingScreenOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) +{ + color[0] = 0.0f; + color[1] = 0.0f; + color[2] = 0.0f; + color[3] = 1.0f; + + if (this->movieClip && data) { + TriangulationData *triangulation = (TriangulationData *) data; + int i; + for (i = 0; i < triangulation->triangles_total; i++) { + int *triangle = triangulation->triangles[i]; + VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]], + *b = &triangulation->triangulated_points[triangle[1]], + *c = &triangulation->triangulated_points[triangle[2]]; + float co[2] = {(float) x, (float) y}, w[3]; + + if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) { + if (barycentric_inside_triangle_v2(w)) { + color[0] += a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2]; + color[1] += a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2]; + color[2] += a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2]; + } + } + } + } +} diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h new file mode 100644 index 00000000000..9d3f44f6be2 --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h @@ -0,0 +1,79 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + + +#ifndef _COM_KeyingScreenOperation_h +#define _COM_KeyingScreenOperation_h + +#include + +#include "COM_NodeOperation.h" + +#include "DNA_scene_types.h" +#include "DNA_movieclip_types.h" + +#include "BLI_listbase.h" + +extern "C" { + #include "BLI_voronoi.h" +} + +/** + * Class with implementation of green screen gradient rasterization + */ +class KeyingScreenOperation : public NodeOperation { +protected: + typedef struct TriangulationData { + VoronoiTriangulationPoint *triangulated_points; + int (*triangles)[3]; + int triangulated_points_total, triangles_total; + } TriangulationData; + + MovieClip *movieClip; + int framenumber; + TriangulationData *cachedTriangulation; + char trackingObject[64]; + + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[], unsigned int preferredResolution[]); + + TriangulationData *buildVoronoiTriangulation(); + + public: + KeyingScreenOperation(); + + void initExecution(); + void deinitExecution(); + + void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); + + void setMovieClip(MovieClip *clip) {this->movieClip = clip;} + void setTrackingObject(char *object) {strncpy(this->trackingObject, object, sizeof(this->trackingObject));} + void setFramenumber(int framenumber) {this->framenumber = framenumber;} + + void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data); +}; + +#endif diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 3c070b4e637..341926f50a3 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2394,6 +2394,36 @@ static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *p uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL); } +static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + bNode *node= ptr->data; + + uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL); + + if (node->id) { + MovieClip *clip = (MovieClip *) node->id; + uiLayout *col; + PointerRNA tracking_ptr; + + RNA_pointer_create(&clip->id, &RNA_MovieTracking, &clip->tracking, &tracking_ptr); + + col = uiLayoutColumn(layout, 1); + uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA); + } +} + +static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + bNode *node= ptr->data; + + uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "dispill_factor", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "clip_white", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "dilate_distance", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "blur_post", 0, NULL, ICON_NONE); +} + /* only once called */ static void node_composit_set_butfunc(bNodeType *ntype) { @@ -2586,7 +2616,12 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_MASK: ntype->uifunc= node_composit_buts_mask; break; - + case CMP_NODE_KEYINGSCREEN: + ntype->uifunc = node_composit_buts_keyingscreen; + break; + case CMP_NODE_KEYING: + ntype->uifunc = node_composit_buts_keying; + break; default: ntype->uifunc = NULL; } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index b2781675cbe..bad40e80265 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -617,6 +617,17 @@ typedef struct TexNodeOutput { char name[64]; } TexNodeOutput; +typedef struct NodeKeyingScreenData { + char tracking_object[64]; +} NodeKeyingScreenData; + +typedef struct NodeKeyingData { + float dispill_factor; + float clip_black, clip_white; + int dilate_distance; + int blur_pre, blur_post; +} NodeKeyingData; + /* frame node flags */ #define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */ #define NODE_FRAME_RESIZEABLE 2 /* test flag, if frame can be resized by user */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 0a0efb66f7f..842ad4156d8 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -341,6 +341,7 @@ extern StructRNA RNA_MotionPathVert; extern StructRNA RNA_MouseSensor; extern StructRNA RNA_MovieSequence; extern StructRNA RNA_MovieClipSequence; +extern StructRNA RNA_MovieTracking; extern StructRNA RNA_MovieTrackingTrack; extern StructRNA RNA_MovieTrackingObject; extern StructRNA RNA_MovieTrackingTrack; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 59c4af4c376..7d2935ece6e 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3046,6 +3046,67 @@ static void def_cmp_mask(StructRNA *srna) RNA_def_property_struct_type(prop, "Mask"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Mask", ""); +} + +static void def_cmp_keyingscreen(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_struct_type(prop, "MovieClip"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Movie Clip", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "NodeKeyingScreenData", "storage"); + + prop = RNA_def_property(srna, "tracking_object", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "tracking_object"); + RNA_def_property_ui_text(prop, "Tracking Object", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); +} + +static void def_cmp_keying(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeKeyingData", "storage"); + + prop = RNA_def_property(srna, "dispill_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "dispill_factor"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Dispill", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "clip_black", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "clip_black"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Clip Black", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "clip_white", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "clip_white"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Clip White", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "blur_pre", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "blur_pre"); + RNA_def_property_range(prop, 0, 2048); + RNA_def_property_ui_text(prop, "Pre Blur", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "blur_post", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "blur_post"); + RNA_def_property_range(prop, 0, 2048); + RNA_def_property_ui_text(prop, "Post Blur", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "dilate_distance", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "dilate_distance"); + RNA_def_property_range(prop, -100, 100); + RNA_def_property_ui_text(prop, "Dilate/Erode", ""); RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); } diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index d5b33f0d01b..d8c27a3677f 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -166,6 +166,8 @@ DefNode( CompositorNode, CMP_NODE_BOKEHIMAGE, def_cmp_bokehimage, "BOKEH DefNode( CompositorNode, CMP_NODE_SWITCH, def_cmp_switch, "SWITCH" ,Switch, "Switch", "" ) DefNode( CompositorNode, CMP_NODE_COLORCORRECTION,def_cmp_colorcorrection,"COLORCORRECTION",ColorCorrection, "ColorCorrection", "" ) DefNode( CompositorNode, CMP_NODE_MASK, def_cmp_mask, "MASK", Mask, "Mask", "" ) +DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYINGSCREEN", KeyingScreen, "KeyingScreen", "" ) +DefNode( CompositorNode, CMP_NODE_KEYING, def_cmp_keying, "KEYING", Keying, "Keying", "" ) DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" ) DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" ) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 5e36f90f217..d07d00a436d 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -76,6 +76,8 @@ set(SRC composite/nodes/node_composite_idMask.c composite/nodes/node_composite_image.c composite/nodes/node_composite_invert.c + composite/nodes/node_composite_keying.c + composite/nodes/node_composite_keyingscreen.c composite/nodes/node_composite_lensdist.c composite/nodes/node_composite_levels.c composite/nodes/node_composite_lummaMatte.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index f850ea91f12..efa107a2223 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -81,6 +81,7 @@ void register_node_type_cmp_bilateralblur(struct bNodeTreeType *ttype); void register_node_type_cmp_vecblur(struct bNodeTreeType *ttype); void register_node_type_cmp_dilateerode(struct bNodeTreeType *ttype); void register_node_type_cmp_defocus(struct bNodeTreeType *ttype); +void register_node_type_cmp_denoise(struct bNodeTreeType *ttype); void register_node_type_cmp_valtorgb(struct bNodeTreeType *ttype); void register_node_type_cmp_rgbtobw(struct bNodeTreeType *ttype); @@ -105,6 +106,8 @@ void register_node_type_cmp_channel_matte(struct bNodeTreeType *ttype); void register_node_type_cmp_color_spill(struct bNodeTreeType *ttype); void register_node_type_cmp_luma_matte(struct bNodeTreeType *ttype); void register_node_type_cmp_doubleedgemask(struct bNodeTreeType *ttype); +void register_node_type_cmp_keyingscreen(struct bNodeTreeType *ttype); +void register_node_type_cmp_keying(struct bNodeTreeType *ttype); void register_node_type_cmp_translate(struct bNodeTreeType *ttype); void register_node_type_cmp_rotate(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c index 3806cf4543a..ff223ac83cf 100644 --- a/source/blender/nodes/composite/node_composite_util.c +++ b/source/blender/nodes/composite/node_composite_util.c @@ -568,6 +568,22 @@ CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel) return valbuf; } +void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel) +{ + float *valf, *rectf; + int tot; + + valf= valbuf->rect; + + /* defaults to returning alpha channel */ + if ((channel < CHAN_R) || (channel > CHAN_A)) channel = CHAN_A; + + rectf = cbuf->rect + channel; + + for (tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4) + *rectf = *valf; +} + static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy) { CompBuf *outbuf; diff --git a/source/blender/nodes/composite/node_composite_util.h b/source/blender/nodes/composite/node_composite_util.h index 51f047b94ff..18dac5dc5c1 100644 --- a/source/blender/nodes/composite/node_composite_util.h +++ b/source/blender/nodes/composite/node_composite_util.h @@ -155,6 +155,7 @@ void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, flo int src1_type, int fac1_type, int src2_type, int fac2_type); CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel); +void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel); void generate_preview(void *data, bNode *node, CompBuf *stackbuf); void do_copy_rgba(bNode *node, float *out, float *in); @@ -220,6 +221,9 @@ void IIR_gauss(CompBuf* src, float sigma, int chan, int xy); #define CMP_SCALE_MAX 12000 CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type); +void node_composit_blur_single_image(bNode *node, int filtertype, int sizex, int sizey, CompBuf *new, CompBuf *img, float scale); +void node_composite_morpho_dilate(CompBuf *cbuf); +void node_composite_morpho_erode(CompBuf *cbuf); float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc); #endif diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.c b/source/blender/nodes/composite/nodes/node_composite_blur.c index d19ea3f202f..9afdd6eadb7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_blur.c +++ b/source/blender/nodes/composite/nodes/node_composite_blur.c @@ -85,9 +85,8 @@ static float *make_bloomtab(int rad) } /* both input images of same type, either 4 or 1 channel */ -static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale) +void node_composit_blur_single_image(bNode *node, int filtertype, int sizex, int sizey, CompBuf *new, CompBuf *img, float scale) { - NodeBlurData *nbd= node->storage; CompBuf *work; register float sum, val; float rval, gval, bval, aval; @@ -101,17 +100,17 @@ static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float sca work= alloc_compbuf(imgx, imgy, img->type, 1); /* allocs */ /* horizontal */ - if (nbd->sizex == 0) { + if (sizex == 0) { memcpy(work->rect, img->rect, sizeof(float) * img->type * imgx * imgy); } else { - rad = scale*(float)nbd->sizex; + rad = scale*(float)sizex; if (rad>imgx/2) rad= imgx/2; else if (rad<1) rad= 1; - gausstab= make_gausstab(nbd->filtertype, rad); + gausstab= make_gausstab(filtertype, rad); gausstabcent= gausstab+rad; for (y = 0; y < imgy; y++) { @@ -152,17 +151,17 @@ static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float sca MEM_freeN(gausstab); } - if (nbd->sizey == 0) { + if (sizey == 0) { memcpy(new->rect, work->rect, sizeof(float) * img->type * imgx * imgy); } else { - rad = scale*(float)nbd->sizey; + rad = scale*(float)sizey; if (rad>imgy/2) rad= imgy/2; else if (rad<1) rad= 1; - gausstab= make_gausstab(nbd->filtertype, rad); + gausstab= make_gausstab(filtertype, rad); gausstabcent= gausstab+rad; bigstep = pix*imgx; @@ -207,6 +206,13 @@ static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float sca free_compbuf(work); } +static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale) +{ + NodeBlurData *nbd = node->storage; + + node_composit_blur_single_image(node, nbd->filtertype, nbd->sizex, nbd->sizey, new, img, scale); +} + /* reference has to be mapped 0-1, and equal in size */ static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *UNUSED(ref), float UNUSED(fac), NodeBlurData *nbd) { diff --git a/source/blender/nodes/composite/nodes/node_composite_dilate.c b/source/blender/nodes/composite/nodes/node_composite_dilate.c index ee857dd0007..1dc56fd4279 100644 --- a/source/blender/nodes/composite/nodes/node_composite_dilate.c +++ b/source/blender/nodes/composite/nodes/node_composite_dilate.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_dilateerode_out[]= { { -1, 0, "" } }; -static void morpho_dilate(CompBuf *cbuf) +void node_composite_morpho_dilate(CompBuf *cbuf) { int x, y; float *p, *rectf = cbuf->rect; @@ -78,7 +78,7 @@ static void morpho_dilate(CompBuf *cbuf) } } -static void morpho_erode(CompBuf *cbuf) +void node_composite_morpho_erode(CompBuf *cbuf) { int x, y; float *p, *rectf = cbuf->rect; @@ -133,11 +133,11 @@ static void node_composit_exec_dilateerode(void *UNUSED(data), bNode *node, bNod if (node->custom2 > 0) { // positive, dilate for (i = 0; i < node->custom2; i++) - morpho_dilate(stackbuf); + node_composite_morpho_dilate(stackbuf); } else if (node->custom2 < 0) { // negative, erode for (i = 0; i > node->custom2; i--) - morpho_erode(stackbuf); + node_composite_morpho_erode(stackbuf); } if (cbuf!=in[0]->data) diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c new file mode 100644 index 00000000000..8e6fd86eae5 --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_keying.c @@ -0,0 +1,218 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_keying.c + * \ingroup cmpnodes + */ + +#include "BLF_translation.h" + +#include "DNA_movieclip_types.h" + +#include "BKE_movieclip.h" + +#include "BLI_listbase.h" +#include "BLI_math_base.h" +#include "BLI_math_color.h" +#include "BLI_voronoi.h" + +#include "node_composite_util.h" + +/* **************** Translate ******************** */ + +static bNodeSocketTemplate cmp_node_keying_in[] = { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "Key Color", 1.0f, 1.0f, 1.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate cmp_node_keying_out[] = { + { SOCK_RGBA, 0, "Image"}, + { SOCK_FLOAT, 0, "Matte"}, + { -1, 0, "" } +}; + +static int get_pixel_primary_channel(float *pixel) +{ + float max_value = MAX3(pixel[0], pixel[1], pixel[2]); + + if (max_value == pixel[0]) + return 0; + else if (max_value == pixel[1]) + return 1; + + return 2; +} + +static float get_pixel_saturation(float *pixel, float screen_balance) +{ + float min = MIN3(pixel[0], pixel[1], pixel[2]); + float max = MAX3(pixel[0], pixel[1], pixel[2]); + float mid = pixel[0] + pixel[1] + pixel[2] - min - max; + float val = (1.0f - screen_balance) * min + screen_balance * mid; + + return max - val; +} + +static void despil_pixel(float *out, float *pixel, float *screen, float screen_gain) +{ + int screen_primary_channel = get_pixel_primary_channel(screen); + float average_value, amount; + + average_value = (pixel[0] + pixel[1] + pixel[2] - pixel[screen_primary_channel]) / 2.0f; + amount = pixel[screen_primary_channel] - average_value; + + if (screen_gain * amount > 0) { + out[screen_primary_channel] = pixel[screen_primary_channel] - screen_gain * amount; + } +} + +static void do_key(bNode *node, float *out, float *pixel, float *screen) +{ + NodeKeyingData *data = node->storage; + + float screen_balance = 0.5f; + float dispill_factor = data->dispill_factor; + float clip_black = data->clip_black; + float clip_white = data->clip_white; + + float saturation = get_pixel_saturation(pixel, screen_balance); + float screen_saturation = get_pixel_saturation(screen, screen_balance); + int primary_channel = get_pixel_primary_channel(pixel); + int screen_primary_channel = get_pixel_primary_channel(screen); + + if (primary_channel != screen_primary_channel) { + /* different main channel means pixel is on foreground, + * but screen color still need to be despilled from it */ + despil_pixel(out, pixel, screen, dispill_factor); + out[3] = 1.0f; + } + else if (saturation >= screen_saturation) { + /* saturation of main channel is more than screen, definitely a background */ + out[0] = 0.0f; + out[1] = 0.0f; + out[2] = 0.0f; + out[3] = 0.0f; + } + else { + float distance; + + despil_pixel(out, pixel, screen, dispill_factor); + + distance = 1.0f - saturation / screen_saturation; + + out[3] = distance; + + if (out[3] < clip_black) + out[3] = 0.0f; + else if (out[3] >= clip_white) + out[3] = 1.0f; + else + out[3] = (out[3] - clip_black) / (clip_white - clip_black); + } +} + +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + if (in[0]->data) { + NodeKeyingData *keying_data = node->storage; + CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA); + CompBuf *keybuf, *mattebuf; + + keybuf = dupalloc_compbuf(cbuf); + + /* single color is used for screen detection */ + composit2_pixel_processor(node, keybuf, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_key, CB_RGBA, CB_VAL); + + /* create a matte from alpha channel */ + mattebuf = valbuf_from_rgbabuf(keybuf, CHAN_A); + + /* apply dilate/erode if needed */ + if (keying_data->dilate_distance != 0) { + int i; + + if (keying_data->dilate_distance > 0) { + for (i = 0; i < keying_data->dilate_distance; i++) + node_composite_morpho_dilate(mattebuf); + } + else { + for (i = 0; i < -keying_data->dilate_distance; i++) + node_composite_morpho_erode(mattebuf); + } + } + + if (keying_data->blur_post > 0.0f) { + /* post-blur of matte */ + CompBuf *newmatte = alloc_compbuf(mattebuf->x, mattebuf->y, mattebuf->type, TRUE); + int size = keying_data->blur_post; + + node_composit_blur_single_image(node, R_FILTER_BOX, size, size, newmatte, mattebuf, 1.0f); + + free_compbuf(mattebuf); + mattebuf = newmatte; + + /* apply blurred matte on output buffer alpha */ + valbuf_to_rgbabuf(mattebuf, keybuf, CHAN_A); + } + + out[0]->data = keybuf; + out[1]->data = mattebuf; + + generate_preview(data, node, keybuf); + + if (cbuf!=in[0]->data) + free_compbuf(cbuf); + } +} + +static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeKeyingData *data; + + data = MEM_callocN(sizeof(NodeKeyingData), "node keying data"); + + data->dispill_factor = 1.0f; + data->clip_black = 0.0f; + data->clip_white = 1.0f; + + node->storage = data; +} + +void register_node_type_cmp_keying(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_KEYING, "Keying", NODE_CLASS_MATTE, NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_keying_in, cmp_node_keying_out); + node_type_size(&ntype, 140, 100, 320); + node_type_init(&ntype, node_composit_init_keying); + node_type_storage(&ntype, "NodeKeyingData", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, exec); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c new file mode 100644 index 00000000000..5cbaf4ae2ba --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c @@ -0,0 +1,202 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_keyingscreen.c + * \ingroup cmpnodes + */ + +#include "BLF_translation.h" + +#include "DNA_movieclip_types.h" + +#include "BKE_movieclip.h" + +#include "BLI_listbase.h" +#include "BLI_math_base.h" +#include "BLI_math_color.h" +#include "BLI_voronoi.h" + +#include "node_composite_util.h" + +/* **************** Translate ******************** */ + +static bNodeSocketTemplate cmp_node_keyingscreen_out[] = { + { SOCK_RGBA, 0, "Screen"}, + { -1, 0, "" } +}; + + +static void compute_gradient_screen(RenderData *rd, NodeKeyingScreenData *keyingscreen_data, MovieClip *clip, CompBuf *screenbuf) +{ + MovieClipUser user = {0}; + MovieTracking *tracking = &clip->tracking; + MovieTrackingTrack *track; + VoronoiTriangulationPoint *triangulated_points; + VoronoiSite *sites; + ImBuf *ibuf; + ListBase *tracksbase; + ListBase edges = {NULL, NULL}; + int sites_total, triangulated_points_total, triangles_total; + int (*triangles)[3]; + int i, x, y; + float *rect = screenbuf->rect; + + if (keyingscreen_data->tracking_object[0]) { + MovieTrackingObject *object = BKE_tracking_named_object(tracking, keyingscreen_data->tracking_object); + + if (!object) + return; + + tracksbase = BKE_tracking_object_tracks(tracking, object); + } + else + tracksbase = BKE_tracking_get_tracks(tracking); + + sites_total = BLI_countlist(tracksbase); + + if (!sites_total) + return; + + BKE_movieclip_user_set_frame(&user, rd->cfra); + ibuf = BKE_movieclip_get_ibuf(clip, &user); + + sites = MEM_callocN(sizeof(VoronoiSite) * sites_total, "keyingscreen voronoi sites"); + track = tracksbase->first; + i = 0; + while (track) { + VoronoiSite *site = &sites[i]; + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, rd->cfra); + ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, 0, FALSE, NULL, NULL); + int j; + + zero_v3(site->color); + for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { + if (pattern_ibuf->rect_float) { + add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); + } + else { + unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; + + site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); + site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); + site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + } + } + + mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); + IMB_freeImBuf(pattern_ibuf); + + site->co[0] = marker->pos[0] * screenbuf->x; + site->co[1] = marker->pos[1] * screenbuf->y; + + track = track->next; + i++; + } + + IMB_freeImBuf(ibuf); + + BLI_voronoi_compute(sites, sites_total, screenbuf->x, screenbuf->y, &edges); + + BLI_voronoi_triangulate(sites, sites_total, &edges, screenbuf->x, screenbuf->y, + &triangulated_points, &triangulated_points_total, + &triangles, &triangles_total); + + for (y = 0; y < screenbuf->y; y++) { + for (x = 0; x < screenbuf->x; x++) { + int index = 4 * (y * screenbuf->x + x); + + rect[index + 0] = rect[index + 1] = rect[index + 2] = 0.0f; + rect[index + 3] = 1.0f; + + for (i = 0; i < triangles_total; i++) { + int *triangle = triangles[i]; + VoronoiTriangulationPoint *a = &triangulated_points[triangle[0]], + *b = &triangulated_points[triangle[1]], + *c = &triangulated_points[triangle[2]]; + float co[2] = {x, y}, w[3]; + + if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) { + if (barycentric_inside_triangle_v2(w)) { + rect[index + 0] += a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2]; + rect[index + 1] += a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2]; + rect[index + 2] += a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2]; + } + } + } + } + } + + MEM_freeN(triangulated_points); + MEM_freeN(triangles); + MEM_freeN(sites); + BLI_freelistN(&edges); +} + +static void exec(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) +{ + NodeKeyingScreenData *keyingscreen_data = node->storage; + RenderData *rd = data; + CompBuf *screenbuf = NULL; + + if (node->id) { + MovieClip *clip = (MovieClip *) node->id; + MovieClipUser user = {0}; + int width, height; + + BKE_movieclip_user_set_frame(&user, rd->cfra); + BKE_movieclip_get_size(clip, &user, &width, &height); + + screenbuf = alloc_compbuf(width, height, CB_RGBA, TRUE); + compute_gradient_screen(rd, keyingscreen_data, clip, screenbuf); + } + + out[0]->data = screenbuf; +} + +static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeKeyingScreenData *data; + + data = MEM_callocN(sizeof(NodeKeyingScreenData), "node keyingscreen data"); + + node->storage = data; +} + +void register_node_type_cmp_keyingscreen(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_KEYINGSCREEN, "Keying Screen", NODE_CLASS_MATTE, NODE_OPTIONS); + node_type_socket_templates(&ntype, NULL, cmp_node_keyingscreen_out); + node_type_size(&ntype, 140, 100, 320); + node_type_init(&ntype, node_composit_init_keyingscreen); + node_type_storage(&ntype, "NodeKeyingScreenData", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, exec); + + nodeRegisterType(ttype, &ntype); +} From b63a2be5c16d9c0c728cf4e07dc565267b9d2a47 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 May 2012 14:54:40 +0000 Subject: [PATCH 102/183] fix for using uninitialized memory when adding spline points, also fix for deleting points not working right. --- source/blender/blenkernel/BKE_mask.h | 2 ++ source/blender/blenkernel/intern/mask.c | 46 ++++++++++++++++++++----- source/blender/editors/mask/mask_ops.c | 9 +++++ 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index d463843e561..d02e6f1966b 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -90,6 +90,8 @@ void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *u /* parenting */ +void BKE_mask_update_display(struct Mask *mask, float ctime); + void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_newframe); void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe); void BKE_mask_parent_init(struct MaskParent *parent); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 439495e8af1..be7fa2fbd74 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1232,24 +1232,54 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) MaskSplinePoint *point_deform = &spline->points_deform[i]; float delta[2]; + *point_deform = *point; + point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; + if (BKE_mask_evaluate_parent_delta(&point->parent, ctime, delta)) { - - *point_deform = *point; - point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; - add_v2_v2(point_deform->bezt.vec[0], delta); add_v2_v2(point_deform->bezt.vec[1], delta); add_v2_v2(point_deform->bezt.vec[2], delta); } - else { - *point_deform = *point; - point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; - } } } } } +/* the purpose of this function is to ensure spline->points_deform is never out of date. + * for now re-evaluate all. eventually this might work differently */ +void BKE_mask_update_display(Mask *mask, float ctime) +{ +#if 0 + MaskObject *maskobj; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + if (spline->points_deform) { + int i = 0; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point; + + if (spline->points_deform) { + point = &spline->points_deform[i]; + BKE_mask_point_free(point); + } + } + if (spline->points_deform) { + MEM_freeN(spline->points_deform); + } + + spline->points_deform = NULL; + } + } + } +#endif + + BKE_mask_evaluate(mask, ctime, FALSE); +} + void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const int do_newframe) { Mask *mask; diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index ded45e73323..44932cab4df 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1230,6 +1230,9 @@ static int add_vertex_exec(bContext *C, wmOperator *op) BKE_mask_calc_handle_point_auto(mask, spline, point, FALSE); BKE_mask_calc_handle_point_auto(mask, spline, point_other, FALSE); + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; } @@ -1249,6 +1252,9 @@ static int add_vertex_exec(bContext *C, wmOperator *op) } } + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + return OPERATOR_FINISHED; } @@ -1495,6 +1501,9 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) } } + /* TODO: only update edited splines */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; From ec4f6750557218be262cacea53ef4cb0ccaa0671 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 29 May 2012 14:55:01 +0000 Subject: [PATCH 103/183] Fixed stupid typo: dispill vs. despill --- source/blender/compositor/CMakeLists.txt | 4 ++-- .../compositor/nodes/COM_KeyingNode.cpp | 22 +++++++++---------- .../blender/compositor/nodes/COM_KeyingNode.h | 2 +- ...ion.cpp => COM_KeyingDespillOperation.cpp} | 16 +++++++------- ...eration.h => COM_KeyingDespillOperation.h} | 14 ++++++------ source/blender/editors/space_node/drawnode.c | 2 +- source/blender/makesdna/DNA_node_types.h | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 6 ++--- .../composite/nodes/node_composite_keying.c | 8 +++---- 9 files changed, 38 insertions(+), 38 deletions(-) rename source/blender/compositor/operations/{COM_KeyingDispillOperation.cpp => COM_KeyingDespillOperation.cpp} (85%) rename source/blender/compositor/operations/{COM_KeyingDispillOperation.h => COM_KeyingDespillOperation.h} (79%) diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index d4e083f9ec1..3e29583756f 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -340,8 +340,8 @@ set(SRC operations/COM_KeyingOperation.h operations/COM_KeyingScreenOperation.cpp operations/COM_KeyingScreenOperation.h - operations/COM_KeyingDispillOperation.cpp - operations/COM_KeyingDispillOperation.h + operations/COM_KeyingDespillOperation.cpp + operations/COM_KeyingDespillOperation.h operations/COM_ColorSpillOperation.cpp operations/COM_ColorSpillOperation.h diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp index 725060371a1..9e29a99293e 100644 --- a/source/blender/compositor/nodes/COM_KeyingNode.cpp +++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp @@ -26,7 +26,7 @@ #include "COM_ExecutionSystem.h" #include "COM_KeyingOperation.h" -#include "COM_KeyingDispillOperation.h" +#include "COM_KeyingDespillOperation.h" #include "COM_SeparateChannelOperation.h" #include "COM_CombineChannelsOperation.h" @@ -135,18 +135,18 @@ OutputSocket *KeyingNode::setupDilateErode(ExecutionSystem *graph, OutputSocket return dilateErodeOperation->getOutputSocket(0); } -OutputSocket *KeyingNode::setupDispill(ExecutionSystem *graph, OutputSocket *dispillInput, InputSocket *inputScreen, float factor) +OutputSocket *KeyingNode::setupDespill(ExecutionSystem *graph, OutputSocket *despillInput, InputSocket *inputScreen, float factor) { - KeyingDispillOperation *dispillOperation = new KeyingDispillOperation(); + KeyingDespillOperation *despillOperation = new KeyingDespillOperation(); - dispillOperation->setDispillFactor(factor); + despillOperation->setDespillFactor(factor); - addLink(graph, dispillInput, dispillOperation->getInputSocket(0)); - inputScreen->relinkConnections(dispillOperation->getInputSocket(1), 1, graph); + addLink(graph, despillInput, despillOperation->getInputSocket(0)); + inputScreen->relinkConnections(despillOperation->getInputSocket(1), 1, graph); - graph->addOperation(dispillOperation); + graph->addOperation(despillOperation); - return dispillOperation->getOutputSocket(0); + return despillOperation->getOutputSocket(0); } void KeyingNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) @@ -198,9 +198,9 @@ void KeyingNode::convertToOperations(ExecutionSystem *graph, CompositorContext * postprocessedImage = alphaOperation->getOutputSocket(); - /* dispill output image */ - if (keying_data->dispill_factor > 0.0f) { - postprocessedImage = setupDispill(graph, postprocessedImage, inputScreen, keying_data->dispill_factor); + /* despill output image */ + if (keying_data->despill_factor > 0.0f) { + postprocessedImage = setupDespill(graph, postprocessedImage, inputScreen, keying_data->despill_factor); } /* connect result to output sockets */ diff --git a/source/blender/compositor/nodes/COM_KeyingNode.h b/source/blender/compositor/nodes/COM_KeyingNode.h index 8c1ee8fdf72..894d0ddc095 100644 --- a/source/blender/compositor/nodes/COM_KeyingNode.h +++ b/source/blender/compositor/nodes/COM_KeyingNode.h @@ -36,7 +36,7 @@ protected: OutputSocket *setupPreBlur(ExecutionSystem *graph, InputSocket *inputImage, int size, OutputSocket **originalImage); OutputSocket *setupPostBlur(ExecutionSystem *graph, OutputSocket *postBLurInput, int size); OutputSocket *setupDilateErode(ExecutionSystem *graph, OutputSocket *dilateErodeInput, int distance); - OutputSocket *setupDispill(ExecutionSystem *graph, OutputSocket *dispillInput, InputSocket *inputSrceen, float factor); + OutputSocket *setupDespill(ExecutionSystem *graph, OutputSocket *despillInput, InputSocket *inputSrceen, float factor); public: KeyingNode(bNode *editorNode); void convertToOperations(ExecutionSystem *graph, CompositorContext *context); diff --git a/source/blender/compositor/operations/COM_KeyingDispillOperation.cpp b/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp similarity index 85% rename from source/blender/compositor/operations/COM_KeyingDispillOperation.cpp rename to source/blender/compositor/operations/COM_KeyingDespillOperation.cpp index 5f4eaf3148d..b7fd2772729 100644 --- a/source/blender/compositor/operations/COM_KeyingDispillOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp @@ -21,7 +21,7 @@ * Sergey Sharybin */ -#include "COM_KeyingDispillOperation.h" +#include "COM_KeyingDespillOperation.h" #include "MEM_guardedalloc.h" @@ -40,31 +40,31 @@ static int get_pixel_primary_channel(float *pixel) return 2; } -KeyingDispillOperation::KeyingDispillOperation(): NodeOperation() +KeyingDespillOperation::KeyingDespillOperation(): NodeOperation() { this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_COLOR); this->addOutputSocket(COM_DT_COLOR); - this->dispillFactor = 0.5f; + this->despillFactor = 0.5f; this->pixelReader = NULL; this->screenReader = NULL; } -void KeyingDispillOperation::initExecution() +void KeyingDespillOperation::initExecution() { this->pixelReader = this->getInputSocketReader(0); this->screenReader = this->getInputSocketReader(1); } -void KeyingDispillOperation::deinitExecution() +void KeyingDespillOperation::deinitExecution() { this->pixelReader = NULL; this->screenReader = NULL; } -void KeyingDispillOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) +void KeyingDespillOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) { float pixelColor[4]; float screenColor[4]; @@ -83,7 +83,7 @@ void KeyingDispillOperation::executePixel(float *color, float x, float y, PixelS color[2] = pixelColor[2]; color[3] = pixelColor[3]; - if (this->dispillFactor * amount > 0) { - color[screen_primary_channel] = pixelColor[screen_primary_channel] - this->dispillFactor * amount; + if (this->despillFactor * amount > 0) { + color[screen_primary_channel] = pixelColor[screen_primary_channel] - this->despillFactor * amount; } } diff --git a/source/blender/compositor/operations/COM_KeyingDispillOperation.h b/source/blender/compositor/operations/COM_KeyingDespillOperation.h similarity index 79% rename from source/blender/compositor/operations/COM_KeyingDispillOperation.h rename to source/blender/compositor/operations/COM_KeyingDespillOperation.h index a918a918381..92a1415a1f0 100644 --- a/source/blender/compositor/operations/COM_KeyingDispillOperation.h +++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.h @@ -21,27 +21,27 @@ * Sergey Sharybin */ -#ifndef _COM_KeyingDispillOperation_h -#define _COM_KeyingDispillOperation_h +#ifndef _COM_KeyingDespillOperation_h +#define _COM_KeyingDespillOperation_h #include "COM_NodeOperation.h" /** - * Class with implementation of keying dispill node + * Class with implementation of keying despill node */ -class KeyingDispillOperation : public NodeOperation { +class KeyingDespillOperation : public NodeOperation { protected: SocketReader *pixelReader; SocketReader *screenReader; - float dispillFactor; + float despillFactor; public: - KeyingDispillOperation(); + KeyingDespillOperation(); void initExecution(); void deinitExecution(); - void setDispillFactor(float value) {this->dispillFactor = value;} + void setDespillFactor(float value) {this->despillFactor = value;} void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]); }; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 341926f50a3..4c5befda8df 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2417,7 +2417,7 @@ static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), Poi bNode *node= ptr->data; uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "dispill_factor", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "despill_factor", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "clip_white", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "dilate_distance", 0, NULL, ICON_NONE); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index bad40e80265..d605e9ac38f 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -622,7 +622,7 @@ typedef struct NodeKeyingScreenData { } NodeKeyingScreenData; typedef struct NodeKeyingData { - float dispill_factor; + float despill_factor; float clip_black, clip_white; int dilate_distance; int blur_pre, blur_post; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 7d2935ece6e..8cd56983d6c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3073,10 +3073,10 @@ static void def_cmp_keying(StructRNA *srna) RNA_def_struct_sdna_from(srna, "NodeKeyingData", "storage"); - prop = RNA_def_property(srna, "dispill_factor", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "dispill_factor"); + prop = RNA_def_property(srna, "despill_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "despill_factor"); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Dispill", ""); + RNA_def_property_ui_text(prop, "Despill", ""); RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "clip_black", PROP_FLOAT, PROP_FACTOR); diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c index 8e6fd86eae5..b5f9b823ac2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keying.c +++ b/source/blender/nodes/composite/nodes/node_composite_keying.c @@ -97,7 +97,7 @@ static void do_key(bNode *node, float *out, float *pixel, float *screen) NodeKeyingData *data = node->storage; float screen_balance = 0.5f; - float dispill_factor = data->dispill_factor; + float despill_factor = data->despill_factor; float clip_black = data->clip_black; float clip_white = data->clip_white; @@ -109,7 +109,7 @@ static void do_key(bNode *node, float *out, float *pixel, float *screen) if (primary_channel != screen_primary_channel) { /* different main channel means pixel is on foreground, * but screen color still need to be despilled from it */ - despil_pixel(out, pixel, screen, dispill_factor); + despil_pixel(out, pixel, screen, despill_factor); out[3] = 1.0f; } else if (saturation >= screen_saturation) { @@ -122,7 +122,7 @@ static void do_key(bNode *node, float *out, float *pixel, float *screen) else { float distance; - despil_pixel(out, pixel, screen, dispill_factor); + despil_pixel(out, pixel, screen, despill_factor); distance = 1.0f - saturation / screen_saturation; @@ -196,7 +196,7 @@ static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode* node, bNo data = MEM_callocN(sizeof(NodeKeyingData), "node keying data"); - data->dispill_factor = 1.0f; + data->despill_factor = 1.0f; data->clip_black = 0.0f; data->clip_white = 1.0f; From e95885322d6e98cd23c538745b1d771101342f61 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 29 May 2012 15:30:56 +0000 Subject: [PATCH 104/183] Fix terrible mistake on merging keying patch which originally was against trunk. This resulted in compositor crashes when using mask node. --- source/blender/compositor/intern/COM_Converter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 747d6495f5d..92eb0f0f92c 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -352,6 +352,7 @@ case CMP_NODE_OUTPUT_FILE: break; case CMP_NODE_MASK: node = new MaskNode(bNode); + break; case CMP_NODE_KEYINGSCREEN: node = new KeyingScreenNode(bNode); break; From 8284b8a56def7d170443370cb3c65fa107c00c65 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 May 2012 20:48:15 +0000 Subject: [PATCH 105/183] mask - border & lasso select (lasso uses Ctrl+Alt - as with clip view) --- source/blender/editors/mask/mask_editor.c | 51 ++++ source/blender/editors/mask/mask_intern.h | 7 + source/blender/editors/mask/mask_select.c | 271 ++++++++++++++++++ .../windowmanager/intern/wm_operators.c | 1 + 4 files changed, 330 insertions(+) diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index 0290934cf9a..990f668af8d 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -89,6 +89,48 @@ void ED_mask_mouse_pos(bContext *C, wmEvent *event, float co[2]) } } +/* input: x/y - mval space + * output: xr/yr - mask point space */ +void ED_mask_point_pos(bContext *C, float x, float y, float *xr, float *yr) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + float co[2]; + + if (sc) { + ED_clip_point_stable_pos(C, x, y, &co[0], &co[1]); + BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co); + } + else { + /* possible other spaces from which mask editing is available */ + zero_v2(co); + } + + *xr = co[0]; + *yr = co[1]; +} + +void ED_mask_point_pos__reverse(bContext *C, float x, float y, float *xr, float *yr) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + ARegion *ar = CTX_wm_region(C); + + float co[2]; + + if (sc && ar) { + co[0] = x; + co[1] = y; + BKE_mask_coord_to_movieclip(sc->clip, &sc->user, co, co); + ED_clip_point_stable_pos__reverse(sc, ar, co, co); + } + else { + /* possible other spaces from which mask editing is available */ + zero_v2(co); + } + + *xr = co[0]; + *yr = co[1]; +} + void ED_mask_size(bContext *C, int *width, int *height) { SpaceClip *sc = CTX_wm_space_clip(C); @@ -158,6 +200,8 @@ void ED_operatortypes_mask(void) /* select */ WM_operatortype_append(MASK_OT_select); WM_operatortype_append(MASK_OT_select_all); + WM_operatortype_append(MASK_OT_select_border); + WM_operatortype_append(MASK_OT_select_lasso); /* shape */ WM_operatortype_append(MASK_OT_slide_point); @@ -204,6 +248,13 @@ void ED_keymap_mask(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0); RNA_enum_set(kmi->ptr, "action", SEL_INVERT); + WM_keymap_add_item(keymap, "MASK_OT_select_border", BKEY, KM_PRESS, 0, 0); + + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT | KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "deselect", TRUE); + /* select clip while in maker view, * this matches View3D functionality where you can select an * object while in editmode to allow vertex parenting */ diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 4eab64b2bcd..28560e4e292 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -71,6 +71,10 @@ void MASK_OT_parent_clear(struct wmOperatorType *ot); void MASK_OT_select(struct wmOperatorType *ot); void MASK_OT_select_all(struct wmOperatorType *ot); +void MASK_OT_select_border(struct wmOperatorType *ot); +void MASK_OT_select_lasso(struct wmOperatorType *ot); +void MASK_OT_select_circle(struct wmOperatorType *ot); + int ED_mask_spline_select_check(struct MaskSplinePoint *points, int tot_point); int ED_mask_select_check(struct Mask *mask); @@ -87,6 +91,9 @@ void ED_mask_aspect(struct bContext *C, float *aspx, float *aspy); void ED_mask_pixelspace_factor(struct bContext *C, float *scalex, float *scaley); void ED_mask_mouse_pos(struct bContext *C, struct wmEvent *event, float co[2]); +void ED_mask_point_pos(struct bContext *C, float x, float y, float *xr, float *yr); +void ED_mask_point_pos__reverse(struct bContext *C, float x, float y, float *xr, float *yr); + /* mask_shapekey.c */ void MASK_OT_shape_key_insert(struct wmOperatorType *ot); void MASK_OT_shape_key_clear(struct wmOperatorType *ot); diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index ae830bb92b5..1286565df73 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -33,6 +33,8 @@ #include "BLI_utildefines.h" #include "BLI_listbase.h" +#include "BLI_rect.h" +#include "BLI_lasso.h" #include "BLI_math.h" #include "BKE_context.h" @@ -312,3 +314,272 @@ void MASK_OT_select(wmOperatorType *ot) RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, "Location", "Location of vertex in normalized space", -1.0f, 1.0f); } + + + +/********************** border select operator *********************/ + +static int border_select_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + int i; + + rcti rect; + rctf rectf; + int change = FALSE, mode, extend; + + /* get rectangle from operator */ + rect.xmin = RNA_int_get(op->ptr, "xmin"); + rect.ymin = RNA_int_get(op->ptr, "ymin"); + rect.xmax = RNA_int_get(op->ptr, "xmax"); + rect.ymax = RNA_int_get(op->ptr, "ymax"); + + ED_mask_point_pos(C, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin); + ED_mask_point_pos(C, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax); + + mode = RNA_int_get(op->ptr, "gesture_mode"); + extend = RNA_boolean_get(op->ptr, "extend"); + + /* do actual selection */ + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + /* TODO: handles? */ + /* TODO: uw? */ + + if (1) { /* can the point be selected? */ + if (BLI_in_rctf(&rectf, point->bezt.vec[1][0], point->bezt.vec[1][1])) { + BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT); + BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT); + } + else if (!extend) { + BKE_mask_point_select_set(point, FALSE); + BKE_mask_point_select_set_handle(point, FALSE); + } + + change = TRUE; + } + } + } + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_select_border(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Border Select"; + ot->description = "Select markers using border selection"; + ot->idname = "MASK_OT_select_border"; + + /* api callbacks */ + ot->invoke = WM_border_select_invoke; + ot->exec = border_select_exec; + ot->modal = WM_border_select_modal; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_gesture_border(ot, TRUE); +} + +static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short select) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + int i; + + rcti rect; + int change = FALSE; + + /* get rectangle from operator */ + BLI_lasso_boundbox(&rect, mcords, moves); + + /* do actual selection */ + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + /* TODO: handles? */ + /* TODO: uw? */ + + float screen_co[2]; + + /* marker in screen coords */ + ED_mask_point_pos__reverse(C, + point->bezt.vec[1][0], point->bezt.vec[1][1], + &screen_co[0], &screen_co[1]); + + if (BLI_in_rcti(&rect, screen_co[0], screen_co[1]) && + BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) + { + BKE_mask_point_select_set(point, select); + BKE_mask_point_select_set_handle(point, select); + } + + change = TRUE; + } + } + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + } + + return change; +} + +static int clip_lasso_select_exec(bContext *C, wmOperator *op) +{ + int mcords_tot; + int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + + if (mcords) { + short select; + + select = !RNA_boolean_get(op->ptr, "deselect"); + do_lasso_select_mask(C, mcords, mcords_tot, select); + + MEM_freeN(mcords); + + return OPERATOR_FINISHED; + } + return OPERATOR_PASS_THROUGH; +} + +void MASK_OT_select_lasso(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Lasso Select"; + ot->description = "Select markers using lasso selection"; + ot->idname = "MASK_OT_select_lasso"; + + /* api callbacks */ + ot->invoke = WM_gesture_lasso_invoke; + ot->modal = WM_gesture_lasso_modal; + ot->exec = clip_lasso_select_exec; + ot->poll = ED_maskediting_mask_poll; + ot->cancel = WM_gesture_lasso_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items"); + RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection instead of deselecting everything first"); +} + +#if 0 +/********************** circle select operator *********************/ + +static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2]) +{ + /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ + float x, y; + + x = (marker->pos[0] - offset[0])*ellipse[0]; + y = (marker->pos[1] - offset[1])*ellipse[1]; + + return x*x + y*y < 1.0f; +} + +static int circle_select_exec(bContext *C, wmOperator *op) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip(sc); + ARegion *ar = CTX_wm_region(C); + MovieTracking *tracking = &clip->tracking; + MovieTrackingTrack *track; + ListBase *tracksbase = BKE_tracking_get_tracks(tracking); + int x, y, radius, width, height, mode, change = FALSE; + float zoomx, zoomy, offset[2], ellipse[2]; + + /* get operator properties */ + x = RNA_int_get(op->ptr, "x"); + y = RNA_int_get(op->ptr, "y"); + radius = RNA_int_get(op->ptr, "radius"); + + mode = RNA_int_get(op->ptr, "gesture_mode"); + + /* compute ellipse and position in unified coordinates */ + ED_space_clip_size(sc, &width, &height); + ED_space_clip_zoom(sc, ar, &zoomx, &zoomy); + + ellipse[0] = width * zoomx / radius; + ellipse[1] = height * zoomy / radius; + + ED_clip_point_stable_pos(C, x, y, &offset[0], &offset[1]); + + /* do selection */ + track = tracksbase->first; + while (track) { + if ((track->flag & TRACK_HIDDEN) == 0) { + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr); + + if (MARKER_VISIBLE(sc, track, marker) && marker_inside_ellipse(marker, offset, ellipse)) { + BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode != GESTURE_MODAL_SELECT); + + change = TRUE; + } + } + + track = track->next; + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_select_circle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Circle Select"; + ot->description = "Select markers using circle selection"; + ot->idname = "MASK_OT_select_circle"; + + /* api callbacks */ + ot->invoke = WM_gesture_circle_invoke; + ot->modal = WM_gesture_circle_modal; + ot->exec = circle_select_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); +} + +#endif diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 42787be8e02..5ae2bcf9c4b 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3936,6 +3936,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "UV_OT_select_border"); WM_modalkeymap_assign(keymap, "CLIP_OT_select_border"); WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_border"); + WM_modalkeymap_assign(keymap, "MASK_OT_select_border"); WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border"); From 03136f06807bff9c08ac7dc6584fb5cdb7bffa51 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 06:07:26 +0000 Subject: [PATCH 106/183] mask object hide/reveal - access from H/Alt+H/Shift+H and eye icon in listview. added alpha setting though its not used for rendering yet. --- source/blender/blenkernel/intern/mask.c | 12 +- .../editors/interface/interface_templates.c | 12 ++ source/blender/editors/mask/mask_draw.c | 6 +- source/blender/editors/mask/mask_editor.c | 12 ++ source/blender/editors/mask/mask_intern.h | 5 + source/blender/editors/mask/mask_ops.c | 135 +++++++++++++++++- .../blender/editors/mask/mask_relationships.c | 8 ++ source/blender/editors/mask/mask_select.c | 58 ++++++-- source/blender/editors/mask/mask_shapekey.c | 8 ++ .../blender/editors/space_clip/space_clip.c | 1 + source/blender/makesdna/DNA_mask_types.h | 13 +- source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_mask.c | 26 ++++ 13 files changed, 271 insertions(+), 26 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index be7fa2fbd74..1e2d65c4dd7 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -94,9 +94,12 @@ MaskObject *BKE_mask_object_new(Mask *mask, const char *name) mask->tot_maskobj++; + maskobj->alpha = 1.0f; + return maskobj; } +/* note: may still be hidden, caller needs to check */ MaskObject *BKE_mask_object_active(Mask *mask) { return BLI_findlink(&mask->maskobjs, mask->act_maskobj); @@ -104,12 +107,7 @@ MaskObject *BKE_mask_object_active(Mask *mask) void BKE_mask_object_active_set(Mask *mask, MaskObject *maskobj) { - int index = BLI_findindex(&mask->maskobjs, maskobj); - - if (index >= 0) - mask->act_maskobj = index; - else - mask->act_maskobj = 0; + mask->act_maskobj = BLI_findindex(&mask->maskobjs, maskobj); } void BKE_mask_object_remove(Mask *mask, MaskObject *maskobj) @@ -1171,7 +1169,7 @@ void BKE_mask_spline_ensure_deform(MaskSpline *spline) spline->points_deform = MEM_mallocN(sizeof(*spline->points_deform) * spline->tot_point, __func__); } else { - printf("alloc spline done\n"); + // printf("alloc spline done\n"); } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 78835192574..54b87fd4509 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2241,6 +2241,18 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiItemL(split, name, ICON_OBJECT_DATA); } } + else if (itemptr->type == &RNA_MaskObject) { + split = uiLayoutSplit(sub, 0.5f, 0); + + uiItemL(split, name, icon); + + uiBlockSetEmboss(block, UI_EMBOSSN); + row = uiLayoutRow(split, 1); + uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE); + uiItemR(row, itemptr, "hide", 0, "", 0); + + uiBlockSetEmboss(block, UI_EMBOSS); + } /* There is a last chance to display custom controls (in addition to the name/label): * If the given item property group features a string property named as prop_list, diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index fe11ded64f4..ae64294fd3e 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -267,9 +267,11 @@ static void draw_maskobjs(Mask *mask) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } -// BKE_mask_spline_ensure_deform(spline); + for (spline = maskobj->splines.first; spline; spline = spline->next) { /* draw curve itself first... */ draw_spline_curve(maskobj, spline); diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index 990f668af8d..5968c80b270 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -203,6 +203,10 @@ void ED_operatortypes_mask(void) WM_operatortype_append(MASK_OT_select_border); WM_operatortype_append(MASK_OT_select_lasso); + /* hide/reveal */ + WM_operatortype_append(MASK_OT_hide_view_clear); + WM_operatortype_append(MASK_OT_hide_view_set); + /* shape */ WM_operatortype_append(MASK_OT_slide_point); WM_operatortype_append(MASK_OT_cyclic_toggle); @@ -255,6 +259,14 @@ void ED_keymap_mask(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "MASK_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT | KM_ALT, 0); RNA_boolean_set(kmi->ptr, "deselect", TRUE); + /* hide/reveal */ + WM_keymap_add_item(keymap, "MASK_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "MASK_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "unselected", FALSE); + + kmi = WM_keymap_add_item(keymap, "MASK_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "unselected", TRUE); + /* select clip while in maker view, * this matches View3D functionality where you can select an * object while in editmode to allow vertex parenting */ diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 28560e4e292..b17d7e7173a 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -51,6 +51,9 @@ void MASK_OT_slide_point(struct wmOperatorType *ot); void MASK_OT_delete(struct wmOperatorType *ot); +void MASK_OT_hide_view_clear(struct wmOperatorType *ot); +void MASK_OT_hide_view_set(struct wmOperatorType *ot); + void MASK_OT_handle_type_set(struct wmOperatorType *ot); int ED_mask_feather_find_nearest( @@ -76,8 +79,10 @@ void MASK_OT_select_lasso(struct wmOperatorType *ot); void MASK_OT_select_circle(struct wmOperatorType *ot); int ED_mask_spline_select_check(struct MaskSplinePoint *points, int tot_point); +int ED_mask_object_select_check(struct MaskObject *maskobj); int ED_mask_select_check(struct Mask *mask); +void ED_mask_object_select_set(struct MaskObject *maskobj, int select); void ED_mask_select_toggle_all(struct Mask *mask, int action); void ED_mask_select_flush_all(struct Mask *mask); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 44932cab4df..5e547d9dec4 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -143,6 +143,10 @@ MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float norma for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -241,6 +245,10 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in int i, tot_feather_point; float *feather_points, *fp; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); for (i = 0; i < spline->tot_point; i++) { @@ -328,6 +336,10 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; @@ -1204,6 +1216,10 @@ static int add_vertex_exec(bContext *C, wmOperator *op) maskobj = BKE_mask_object_active(mask); + if (maskobj && maskobj->restrictflag & MASK_RESTRICT_VIEW) { + maskobj = NULL; + } + RNA_float_get_array(op->ptr, "location", co); if (maskobj && maskobj->act_point && MASKPOINT_ISSEL(maskobj->act_point)) { @@ -1360,6 +1376,10 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { spline->flag ^= MASK_SPLINE_CYCLIC; @@ -1432,7 +1452,13 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) int mask_object_shape_ofs = 0; for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline = maskobj->splines.first; + MaskSpline *spline; + + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + + spline = maskobj->splines.first; while (spline) { const int tot_point_orig = spline->tot_point; @@ -1537,6 +1563,10 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) MaskSpline *spline; int i; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; @@ -1581,3 +1611,106 @@ void MASK_OT_handle_type_set(wmOperatorType *ot) /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type"); } + + +/* ********* clear/set restrict view *********/ +static int mask_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + int changed = FALSE; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + + if (maskobj->restrictflag & OB_RESTRICT_VIEW) { + ED_mask_object_select_set(maskobj, TRUE); + maskobj->restrictflag &= ~OB_RESTRICT_VIEW; + changed = 1; + } + } + + if (changed) { + WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MASK_OT_hide_view_clear(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name = "Clear Restrict View"; + ot->description = "Reveal the object by setting the hide flag"; + ot->idname = "MASK_OT_hide_view_clear"; + + /* api callbacks */ + ot->exec = mask_hide_view_clear_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mask_hide_view_set_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + const int unselected = RNA_boolean_get(op->ptr, "unselected"); + int changed = FALSE; + + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + if (!unselected) { + if (ED_mask_object_select_check(maskobj)) { + ED_mask_object_select_set(maskobj, FALSE); + + maskobj->restrictflag |= OB_RESTRICT_VIEW; + changed = 1; + if (maskobj == BKE_mask_object_active(mask)) { + BKE_mask_object_active_set(mask, NULL); + } + } + } + else { + if (!ED_mask_object_select_check(maskobj)) { + maskobj->restrictflag |= OB_RESTRICT_VIEW; + changed = 1; + if (maskobj == BKE_mask_object_active(mask)) { + BKE_mask_object_active_set(mask, NULL); + } + } + } + } + + if (changed) { + WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MASK_OT_hide_view_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Set Restrict View"; + ot->description = "Hide the object by setting the hide flag"; + ot->idname = "MASK_OT_hide_view_set"; + + /* api callbacks */ + ot->exec = mask_hide_view_set_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); + +} diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 4d08e2fa439..2d2c527d961 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -66,6 +66,10 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) MaskSpline *spline; int i; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; @@ -132,6 +136,10 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) MaskSpline *spline; int i; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 1286565df73..482abbe5818 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -71,23 +71,52 @@ int ED_mask_spline_select_check(MaskSplinePoint *points, int tot_point) return FALSE; } +int ED_mask_object_select_check(MaskObject *maskobj) +{ + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { + return TRUE; + } + } + + return FALSE; +} + int ED_mask_select_check(Mask *mask) { MaskObject *maskobj; for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline; - - for (spline = maskobj->splines.first; spline; spline = spline->next) { - if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { - return TRUE; - } + if (ED_mask_object_select_check(maskobj)) { + return TRUE; } } return FALSE; } +void ED_mask_object_select_set(MaskObject *maskobj, int select) +{ + MaskSpline *spline; + + for (spline = maskobj->splines.first; spline; spline = spline->next) { + int i; + + if (select) + spline->flag |= SELECT; + else + spline->flag &= ~SELECT; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + BKE_mask_point_select_set(point, select); + } + } +} + void ED_mask_select_toggle_all(Mask *mask, int action) { MaskObject *maskobj; @@ -100,17 +129,12 @@ void ED_mask_select_toggle_all(Mask *mask, int action) } for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { - int i; - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - - BKE_mask_point_select_set(point, (action == SEL_SELECT) ? TRUE : FALSE); - } + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; } + + ED_mask_object_select_set(maskobj, (action == SEL_SELECT) ? TRUE : FALSE); } } @@ -121,6 +145,10 @@ void ED_mask_select_flush_all(Mask *mask) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 7a91fbeed13..71b10ae0da3 100755 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -67,6 +67,10 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op)) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskObjectShape *maskobj_shape; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + maskobj_shape = BKE_mask_object_shape_varify_frame(maskobj, frame); BKE_mask_object_shape_from_mask(maskobj, maskobj_shape); change = TRUE; @@ -109,6 +113,10 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskObjectShape *maskobj_shape; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + maskobj_shape = BKE_mask_object_shape_find_frame(maskobj, frame); if (maskobj_shape) { diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index c6d35b03468..f952d6bbe47 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -369,6 +369,7 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) switch(wmn->data) { case ND_SELECT: case ND_DATA: + case ND_DRAW: ED_area_tag_redraw(sa); break; } diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index cf3f5e77544..65707725a53 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -44,7 +44,7 @@ typedef struct Mask { ID id; struct AnimData *adt; ListBase maskobjs; /* mask objects */ - int act_maskobj; /* index of active mask object */ + int act_maskobj; /* index of active mask object (-1 == None) */ int tot_maskobj; /* total number of mask objects */ } Mask; @@ -107,12 +107,18 @@ typedef struct MaskObject { struct MaskSpline *act_spline; /* active spline */ struct MaskSplinePoint *act_point; /* active point */ + + float alpha; + //char flag; /* not used yet */ + char restrictflag; /* matching 'Object' flag of the same name - eventually use in the outliner */ + char pad[3]; } MaskObject; /* MaskParent->flag */ #define MASK_PARENT_ACTIVE (1 << 0) /* MaskSpline->flag */ +/* reserve (1 << 0) for SELECT */ #define MASK_SPLINE_CYCLIC (1 << 1) /* MaskSpline->weight_interp */ @@ -121,4 +127,9 @@ typedef struct MaskObject { #define MASK_OBJECT_SHAPE_ELEM_SIZE 8 /* 3x 2D points + weight + radius == 8 */ +/* ob->restrictflag */ +#define MASK_RESTRICT_VIEW 1 +#define MASK_RESTRICT_SELECT 2 +#define MASK_RESTRICT_RENDER 4 + #endif // __DNA_MASK_TYPES_H__ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 532f971ad0a..9c465619b95 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -306,6 +306,7 @@ extern StructRNA RNA_MaterialSubsurfaceScattering; extern StructRNA RNA_MaterialTextureSlot; extern StructRNA RNA_MaterialVolume; extern StructRNA RNA_Mask; +extern StructRNA RNA_MaskObject; extern StructRNA RNA_Menu; extern StructRNA RNA_Mesh; extern StructRNA RNA_MeshColor; diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 1345011cd7e..393ca5f3244 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -533,6 +533,32 @@ static void rna_def_mask_object(BlenderRNA *brna) RNA_def_property_struct_type(prop, "MaskSpline"); RNA_def_property_ui_text(prop, "Splines", "Collection of splines which defines this object"); RNA_def_property_srna(prop, "MaskSplines"); + + /* restrict */ + prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_VIEW); + RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1); + RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_SELECT); + RNA_def_property_ui_text(prop, "Restrict Select", "Restrict selection in the viewport"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 1); + RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_RENDER); + RNA_def_property_ui_text(prop, "Restrict Render", "Restrict renderability"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1); + RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); + + /* render settings */ + prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "alpha"); + RNA_def_property_range(prop, 0.0, 1.0f); + RNA_def_property_ui_text(prop, "Opacity", "Render Opacity"); + RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); } static void rna_def_maskobjects(BlenderRNA *brna, PropertyRNA *cprop) From eb6a6edc3d7ceb6dfb9e610e3fb0756fdf7e7e82 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 06:33:44 +0000 Subject: [PATCH 107/183] circle select for mask view (Ckey) --- source/blender/editors/mask/mask_editor.c | 2 + source/blender/editors/mask/mask_select.c | 87 +++++++++++-------- .../windowmanager/intern/wm_operators.c | 1 + 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index 5968c80b270..aa8a9cbddcc 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -202,6 +202,7 @@ void ED_operatortypes_mask(void) WM_operatortype_append(MASK_OT_select_all); WM_operatortype_append(MASK_OT_select_border); WM_operatortype_append(MASK_OT_select_lasso); + WM_operatortype_append(MASK_OT_select_circle); /* hide/reveal */ WM_operatortype_append(MASK_OT_hide_view_clear); @@ -253,6 +254,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf) RNA_enum_set(kmi->ptr, "action", SEL_INVERT); WM_keymap_add_item(keymap, "MASK_OT_select_border", BKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_select_circle", CKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "MASK_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_ALT, 0); RNA_boolean_set(kmi->ptr, "deselect", FALSE); diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 482abbe5818..679f25aafea 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -145,15 +145,17 @@ void ED_mask_select_flush_all(Mask *mask) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { - continue; - } - for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; spline->flag &= ~SELECT; + /* intentionally _dont_ do this in the maskobj loop + * so we clear flags on all splines */ + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *cur_point = &spline->points[i]; @@ -373,6 +375,10 @@ static int border_select_exec(bContext *C, wmOperator *op) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; @@ -380,18 +386,16 @@ static int border_select_exec(bContext *C, wmOperator *op) /* TODO: handles? */ /* TODO: uw? */ - if (1) { /* can the point be selected? */ - if (BLI_in_rctf(&rectf, point->bezt.vec[1][0], point->bezt.vec[1][1])) { - BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT); - BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT); - } - else if (!extend) { - BKE_mask_point_select_set(point, FALSE); - BKE_mask_point_select_set_handle(point, FALSE); - } - - change = TRUE; + if (BLI_in_rctf(&rectf, point->bezt.vec[1][0], point->bezt.vec[1][1])) { + BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT); + BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT); } + else if (!extend) { + BKE_mask_point_select_set(point, FALSE); + BKE_mask_point_select_set_handle(point, FALSE); + } + + change = TRUE; } } } @@ -443,6 +447,10 @@ static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; @@ -519,28 +527,27 @@ void MASK_OT_select_lasso(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection instead of deselecting everything first"); } -#if 0 /********************** circle select operator *********************/ -static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2]) +static int mask_spline_point_inside_ellipse(MaskSplinePoint *point, float offset[2], float ellipse[2]) { /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ float x, y; - x = (marker->pos[0] - offset[0])*ellipse[0]; - y = (marker->pos[1] - offset[1])*ellipse[1]; + x = (point->bezt.vec[1][0] - offset[0]) * ellipse[0]; + y = (point->bezt.vec[1][1] - offset[1]) * ellipse[1]; return x*x + y*y < 1.0f; } static int circle_select_exec(bContext *C, wmOperator *op) { + Mask *mask = CTX_data_edit_mask(C); + MaskObject *maskobj; + int i; + SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip(sc); ARegion *ar = CTX_wm_region(C); - MovieTracking *tracking = &clip->tracking; - MovieTrackingTrack *track; - ListBase *tracksbase = BKE_tracking_get_tracks(tracking); int x, y, radius, width, height, mode, change = FALSE; float zoomx, zoomy, offset[2], ellipse[2]; @@ -551,29 +558,37 @@ static int circle_select_exec(bContext *C, wmOperator *op) mode = RNA_int_get(op->ptr, "gesture_mode"); + /* TODO - make generic! - this is SpaceClip only! */ /* compute ellipse and position in unified coordinates */ ED_space_clip_size(sc, &width, &height); ED_space_clip_zoom(sc, ar, &zoomx, &zoomy); + width = height = MAX2(width, height); ellipse[0] = width * zoomx / radius; ellipse[1] = height * zoomy / radius; - ED_clip_point_stable_pos(C, x, y, &offset[0], &offset[1]); + ED_mask_point_pos(C, x, y, &offset[0], &offset[1]); - /* do selection */ - track = tracksbase->first; - while (track) { - if ((track->flag & TRACK_HIDDEN) == 0) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr); + /* do actual selection */ + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + MaskSpline *spline; - if (MARKER_VISIBLE(sc, track, marker) && marker_inside_ellipse(marker, offset, ellipse)) { - BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode != GESTURE_MODAL_SELECT); - - change = TRUE; - } + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; } - track = track->next; + for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (mask_spline_point_inside_ellipse(point, offset, ellipse)) { + BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT); + BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT); + + change = TRUE; + } + } + } } if (change) { @@ -609,5 +624,3 @@ void MASK_OT_select_circle(wmOperatorType *ot) RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); } - -#endif diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 5ae2bcf9c4b..d7d55885f37 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3853,6 +3853,7 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle"); WM_modalkeymap_assign(keymap, "UV_OT_circle_select"); WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle"); + WM_modalkeymap_assign(keymap, "MASK_OT_select_circle"); } From 6bee4c7a8f739f9d7f1745c57ce1cb5aa5a69220 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 06:42:03 +0000 Subject: [PATCH 108/183] transform wasnt ignoring hidden maskobjects --- .../editors/transform/transform_conversions.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index dd6a5c555be..9dd064e5e07 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5975,7 +5975,11 @@ static void createTransMaskingData(bContext *C, TransInfo *t) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline = maskobj->splines.first; - while (spline) { + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -5988,8 +5992,6 @@ static void createTransMaskingData(bContext *C, TransInfo *t) t->total += 1; } } - - spline = spline->next; } } @@ -6008,7 +6010,11 @@ static void createTransMaskingData(bContext *C, TransInfo *t) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline = maskobj->splines.first; - while (spline) { + if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -6029,8 +6035,6 @@ static void createTransMaskingData(bContext *C, TransInfo *t) } } } - - spline = spline->next; } } } From c93bfdd78bb4d7f8dab01a3c1708120df26fd647 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 07:15:09 +0000 Subject: [PATCH 109/183] proportional editing for mask transform --- .../blender/editors/space_clip/space_clip.c | 3 ++ .../editors/transform/transform_conversions.c | 44 ++++++++++++++----- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index f952d6bbe47..7f77dcb5659 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -52,6 +52,7 @@ #include "IMB_imbuf_types.h" #include "ED_mask.h" +#include "ED_space_api.h" #include "ED_screen.h" #include "ED_clip.h" #include "ED_transform.h" @@ -1137,6 +1138,8 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) ED_mask_draw((bContext *)C); + ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); + glPopMatrix(); } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9dd064e5e07..f563a7a089d 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5885,17 +5885,19 @@ typedef struct TransDataMasking{ MaskSplinePoint *point; } TransDataMasking; -static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, TransData *td, TransData2D *td2d, TransDataMasking *tdm) +static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, + TransData *td, TransData2D *td2d, TransDataMasking *tdm, int propmode) { BezTriple *bezt = &point->bezt; float aspx, aspy; + short is_sel_point = MASKPOINT_ISSEL(point); tdm->point = point; copy_m3_m3(tdm->vec, bezt->vec); ED_space_clip_mask_aspect(sc, &aspx, &aspy); - if (MASKPOINT_CV_ISSEL(point)) { + if (propmode || is_sel_point) { int i; for (i = 0; i < 3; i++) { /* CV coords are scaled by aspects. this is needed for rotations and @@ -5918,7 +5920,9 @@ static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, TransDat td->ext= NULL; td->val= NULL; - td->flag |= TD_SELECTED; + if (is_sel_point) { + td->flag |= TD_SELECTED; + } td->dist= 0.0; unit_m3(td->mtx); @@ -5951,7 +5955,10 @@ static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, TransDat td->ext= NULL; td->val= NULL; - td->flag |= TD_SELECTED; + if (is_sel_point) { + td->flag |= TD_SELECTED; + } + td->dist= 0.0; unit_m3(td->mtx); @@ -5970,6 +5977,8 @@ static void createTransMaskingData(bContext *C, TransInfo *t) TransData *td = NULL; TransData2D *td2d = NULL; TransDataMasking *tdm = NULL; + int count = 0, countsel = 0; + int propmode = t->flag & T_PROP_EDIT; /* count */ for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { @@ -5987,17 +5996,21 @@ static void createTransMaskingData(bContext *C, TransInfo *t) if (MASKPOINT_ISSEL(point)) { if (MASKPOINT_CV_ISSEL(point)) - t->total += 3; + countsel += 3; else - t->total += 1; + countsel += 1; } + + if (propmode) + count += 3; } } } - if (t->total == 0) - return; + /* note: in prop mode we need at least 1 selected */ + if (countsel == 0) return; + t->total = (propmode) ? count: countsel; td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransObData(Mask Editing)"); /* for each 2d uv coord a 3d vector is allocated, so that they can be * treated just as if they were 3d verts */ @@ -6020,10 +6033,10 @@ static void createTransMaskingData(bContext *C, TransInfo *t) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - if (MASKPOINT_ISSEL(point)) { - MaskPointToTransData(sc, point, td, td2d, tdm); + if (propmode || MASKPOINT_ISSEL(point)) { + MaskPointToTransData(sc, point, td, td2d, tdm, propmode); - if (MASKPOINT_CV_ISSEL(point)) { + if (propmode || MASKPOINT_CV_ISSEL(point)) { td += 3; td2d += 3; tdm += 3; @@ -6130,8 +6143,15 @@ void createTransData(bContext *C, TransInfo *t) t->flag |= T_POINTS|T_2D_EDIT; if (t->options & CTX_MOVIECLIP) createTransTrackingData(C, t); - else if (t->options & CTX_MASK) + else if (t->options & CTX_MASK) { createTransMaskingData(C, t); + + if (t->data && (t->flag & T_PROP_EDIT)) { + sort_trans_data(t); // makes selected become first in array + set_prop_dist(t, TRUE); + sort_trans_data_dist(t); + } + } } else if (t->obedit) { t->ext = NULL; From a111662e1aac5964ccbcc432bed701866e374359 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 07:34:25 +0000 Subject: [PATCH 110/183] proportional editing for masks --- release/scripts/startup/bl_ui/space_clip.py | 7 +++++++ source/blender/editors/transform/transform.c | 7 ++----- .../blender/editors/transform/transform_generics.c | 14 ++++++++++++++ source/blender/makesdna/DNA_scene_types.h | 3 ++- source/blender/makesrna/intern/rna_scene.c | 6 ++++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index c6ea5633f23..0211ffd0c9f 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -75,8 +75,15 @@ class CLIP_HT_header(Header): row.template_ID(sc, "clip", open='clip.open') if sc.mode == 'MASKEDITING': + toolsettings = context.tool_settings + row = layout.row() row.template_ID(sc, "mask", new="mask.new") + + row = layout.row(align=True) + row.prop(toolsettings, "use_proportional_edit_mask", text="", icon_only=True) + if toolsettings.use_proportional_edit_objects: + row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True) if clip: tracking = clip.tracking diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index b80b6d6a1bc..cb2eaf7aef9 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1517,6 +1517,8 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) { if (t->obedit) ts->proportional = proportional; + else if (t->options & CTX_MASK) + ts->proportional_mask = (proportional != PROP_EDIT_OFF); else ts->proportional_objects = (proportional != PROP_EDIT_OFF); } @@ -1650,13 +1652,8 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_CLIP) { - SpaceClip *sc = CTX_wm_space_clip(C); unit_m3(t->spacemtx); t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - if (ED_space_clip_show_trackedit(sc)) - t->options |= CTX_MOVIECLIP; - else if (ED_space_clip_show_maskedit(sc)) - t->options |= CTX_MASK; } else unit_m3(t->spacemtx); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 985a393f238..46ee80aff5b 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1127,6 +1127,11 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) SpaceClip *sclip = sa->spacedata.first; t->view = &ar->v2d; t->around = sclip->around; + + if (ED_space_clip_show_trackedit(sclip)) + t->options |= CTX_MOVIECLIP; + else if (ED_space_clip_show_maskedit(sclip)) + t->options |= CTX_MASK; } else { if (ar) { @@ -1189,6 +1194,15 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->flag |= T_PROP_CONNECTED; } } + else if (t->options & CTX_MASK) { + if (ts->proportional_mask) { + t->flag |= T_PROP_EDIT; + + if (ts->proportional == PROP_EDIT_CONNECTED) { + t->flag |= T_PROP_CONNECTED; + } + } + } else if (t->obedit == NULL && ts->proportional_objects) { t->flag |= T_PROP_EDIT; } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 198b6a9bf80..75b0b18879d 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -999,7 +999,8 @@ typedef struct ToolSettings { short snap_flag, snap_target; short proportional, prop_mode; char proportional_objects; /* proportional edit, object mode */ - char pad[5]; + char proportional_mask; /* proportional edit, object mode */ + char pad[4]; char auto_normalize; /*auto normalizing mode in wpaint*/ char multipaint; /* paint multiple bones in wpaint */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 17efc25c132..646118debb5 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1565,6 +1565,12 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "use_proportional_edit_mask", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proportional_mask", 0); + RNA_def_property_ui_text(prop, "Proportional Editing Objects", "Proportional editing mask mode"); + RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "proportional_edit_falloff", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "prop_mode"); RNA_def_property_enum_items(prop, proportional_falloff_items); From c53c19ce32a4a8f118091bf6452ff77ecec05d12 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 08:20:20 +0000 Subject: [PATCH 111/183] proportional editing keys now work when editing masks. --- source/blender/editors/include/ED_object.h | 1 + source/blender/editors/mask/mask_editor.c | 5 +++++ source/blender/editors/object/object_ops.c | 8 +++++++ .../blender/editors/space_clip/space_clip.c | 21 +++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 8dc83df2977..9c10a270ef8 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -90,6 +90,7 @@ struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob); void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); +void ED_keymap_proportional_maskmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, const short do_connected); diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index aa8a9cbddcc..a0b47be8ea3 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -42,6 +42,7 @@ #include "ED_screen.h" #include "ED_mask.h" +#include "ED_object.h" /* ED_keymap_proportional_maskmode only */ #include "ED_clip.h" #include "ED_transform.h" @@ -232,6 +233,10 @@ void ED_keymap_mask(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MASK_OT_new", NKEY, KM_PRESS, KM_ALT, 0); + /* mask mode supports PET now */ + ED_keymap_proportional_cycle(keyconf, keymap); + ED_keymap_proportional_maskmode(keyconf, keymap); + /* geometry */ WM_keymap_add_item(keymap, "MASK_OT_add_vertex_slide", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MASK_OT_add_feather_vertex_slide", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 6e653eff57c..d0a93302b7f 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -441,6 +441,14 @@ void ED_keymap_proportional_obmode(struct wmKeyConfig *UNUSED(keyconf), struct w RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_edit_objects"); } +void ED_keymap_proportional_maskmode(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap) +{ + wmKeyMapItem *kmi; + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_edit_mask"); +} + void ED_keymap_proportional_editmode(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap, const short do_connected) { diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 7f77dcb5659..8c5ae38011d 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1317,6 +1317,26 @@ static void clip_header_area_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } +static void clip_header_area_listener(ARegion *ar, wmNotifier *wmn) +{ + /* context changes */ + switch (wmn->category) { + case NC_SCENE: + switch (wmn->data) { + /* for proportional editmode only */ + case ND_TOOLSETTINGS: + /* TODO - should do this when in mask mode only but no datas available */ + // if(sc->mode == SC_MODE_MASKEDITING) + { + ED_region_tag_redraw(ar); + } + break; + } + break; + } +} + + /****************** tools region ******************/ /* add handlers, stuff you only do once or on area/region changes */ @@ -1478,6 +1498,7 @@ void ED_spacetype_clip(void) art->init = clip_header_area_init; art->draw = clip_header_area_draw; + art->listener = clip_header_area_listener; BLI_addhead(&st->regiontypes, art); From 1116731d97638dc284732b1bbcbc02523f38ad30 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 10:24:34 +0000 Subject: [PATCH 112/183] make rasterizer thread safe. --- intern/raskter/raskter.c | 60 +++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index cf8d76372e7..2cd1b38d525 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -55,8 +55,11 @@ struct r_buffer_stats { int sizey; }; -static struct e_status *all_edges, *possible_edges; -static struct r_buffer_stats rb; +struct r_fill_context { + struct e_status *all_edges, *possible_edges; + struct r_buffer_stats rb; +}; + /* * Sort all the edges of the input polygon by Y, then by X, of the "first" vertex encountered. * This will ensure we can scan convert the entire poly in one pass. @@ -65,7 +68,7 @@ static struct r_buffer_stats rb; * just the poly. Since the DEM code could end up being coupled with this, we'll keep it separate * for now. */ -static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct e_status *open_edge) +static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge) { int i; int xbeg; @@ -82,7 +85,7 @@ static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct struct poly_vert *v; /* set up pointers */ v = verts; - all_edges = NULL; + ctx->all_edges = NULL; /* loop all verts */ for (i = 0; i < num_verts; i++) { /* determine beginnings and endings of edges, linking last vertex to first vertex */ @@ -148,7 +151,7 @@ static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct e_new->drift_inc = xdist % dy; e_new->xshift = (xdist / dy) * e_new->xdir; } - next_edge_ref = &all_edges; + next_edge_ref = &ctx->all_edges; /* link in all the edges, in sorted order */ for (;; ) { next_edge = *next_edge_ref; @@ -168,7 +171,7 @@ static void preprocess_all_edges(struct poly_vert *verts, int num_verts, struct * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need * if it ends up being coupled with this function. */ -int rast_scan_fill(struct poly_vert *verts, int num_verts) +int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts) { int x_curr; /* current pixel position in X */ int y_curr; /* current scan line being drawn */ @@ -208,13 +211,13 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) * Do some preprocessing on all edges. This constructs a table structure in memory of all * the edge properties and can "flip" some edges so sorting works correctly. */ - preprocess_all_edges(verts, num_verts, edgbuf); + preprocess_all_edges(ctx, verts, num_verts, edgbuf); /* * Set the pointer for tracking the edges currently in processing to NULL to make sure * we don't get some crazy value after initialization. */ - possible_edges = NULL; + ctx->possible_edges = NULL; /* * Loop through all scan lines to be drawn. Since we sorted by Y values during @@ -229,7 +232,7 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. * Will get changed once DEM code gets in. */ - for (y_curr = MAX2(all_edges->ybeg, 0); (all_edges || possible_edges) && (y_curr < rb.sizey); y_curr++) { + for (y_curr = MAX2(ctx->all_edges->ybeg, 0); (ctx->all_edges || ctx->possible_edges) && (y_curr < ctx->rb.sizey); y_curr++) { /* * Link any edges that start on the current scan line into the list of @@ -246,16 +249,16 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) * * At each iteration, make sure we still have a non-NULL edge. */ - for (edgec = &possible_edges; all_edges && (all_edges->ybeg == y_curr); ) { - x_curr = all_edges->x; /* Set current X position. */ + for (edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr); ) { + x_curr = ctx->all_edges->x; /* Set current X position. */ for (;; ) { /* Start looping edges. Will break when edges run out. */ e_curr = *edgec; /* Set up a current edge pointer. */ if (!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ - e_temp = all_edges->e_next; /* set a temp "next" edge to test. */ - *edgec = all_edges; /* Add this edge to the list to be scanned. */ - all_edges->e_next = e_curr; /* Set up the next edge. */ - edgec = &all_edges->e_next; /* Set our list to the next edge's location in memory. */ - all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ + e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */ + *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */ + ctx->all_edges->e_next = e_curr; /* Set up the next edge. */ + edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */ + ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ break; /* Stop looping edges (since we ran out or hit empty X span. */ } else { @@ -268,11 +271,11 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) * Determine the current scan line's offset in the pixel buffer based on its Y position. * Basically we just multiply the current scan line's Y value by the number of pixels in each line. */ - yp = y_curr * rb.sizex; + yp = y_curr * ctx->rb.sizex; /* * Set a "scan line pointer" in memory. The location of the buffer plus the row offset. */ - spxl = rb.buf + (yp); + spxl = ctx->rb.buf + (yp); /* * Set up the current edge to the first (in X) edge. The edges which could possibly be in this * list were determined in the preceeding edge loop above. They were already sorted in X by the @@ -281,7 +284,7 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge * we will eventually hit a NULL when the list runs out. */ - for (e_curr = possible_edges; e_curr; e_curr = e_curr->e_next) { + for (e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) { /* * Calculate a span of pixels to fill on the current scan line. * @@ -300,7 +303,7 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) /* set up xmin and xmax bounds on this scan line */ cpxl = spxl + MAX2(e_curr->x, 0); e_curr = e_curr->e_next; - mpxl = spxl + MIN2(e_curr->x, rb.sizex) - 1; + mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; /* draw the pixels. */ for (; cpxl <= mpxl; cpxl++){ @@ -321,7 +324,7 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) * polygons, we dont have fractional positions, so we only move in x-direction * when needed to get all the way to the next pixel over... */ - for (edgec = &possible_edges; (e_curr = *edgec); ) { + for (edgec = &ctx->possible_edges; (e_curr = *edgec); ) { if (!(--(e_curr->num))) { *edgec = e_curr->e_next; } @@ -342,8 +345,8 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) * pass, then we know we need to sort by x, so then cycle through edges again and perform * the sort.- */ - if (possible_edges) { - for (edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + if (ctx->possible_edges) { + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ if (e_curr->x > e_curr->e_next->x) { *edgec = e_curr->e_next; @@ -359,7 +362,7 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) for (;; ) { /* reset exchange flag so it's only set if we encounter another one */ swixd = 0; - for (edgec = &possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */ if (e_curr->x > e_curr->e_next->x) { *edgec = e_curr->e_next; @@ -386,6 +389,7 @@ int rast_scan_fill(struct poly_vert *verts, int num_verts) int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { int i; /* i: Loop counter. */ struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ + struct r_fill_context ctx = {0}; /* * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert @@ -411,11 +415,11 @@ int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { ply[i].y = (verts[(i << 1) + 1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */ } - rb.buf = buf; /* Set the output buffer pointer. */ - rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ - rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ + ctx.rb.buf = buf; /* Set the output buffer pointer. */ + ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ + ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ - i = rast_scan_fill(ply, num); /* Call our rasterizer, passing in the integer coords for each vert. */ + i = rast_scan_fill(&ctx, ply, num); /* Call our rasterizer, passing in the integer coords for each vert. */ free(ply); /* Free the memory allocated for the integer coordinate table. */ return(i); /* Return the value returned by the rasterizer. */ } From ad00c1210acdfd49ffb3cf1eb4c22ccea054d855 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 11:52:44 +0000 Subject: [PATCH 113/183] rename macros for mask point selection - were a bit confusing. --- source/blender/blenkernel/BKE_mask.h | 18 +++++++++--------- source/blender/blenkernel/intern/curve.c | 3 +-- source/blender/blenkernel/intern/mask.c | 8 ++++---- source/blender/editors/mask/mask_draw.c | 6 +++--- source/blender/editors/mask/mask_ops.c | 16 ++++++++-------- .../blender/editors/mask/mask_relationships.c | 4 ++-- source/blender/editors/mask/mask_select.c | 8 ++++---- .../editors/transform/transform_conversions.c | 10 +++++----- 8 files changed, 36 insertions(+), 37 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index d02e6f1966b..e21a2aa54e8 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -135,16 +135,16 @@ void BKE_mask_object_shape_changed_remove(struct MaskObject *maskobj, int index, /* rasterization */ void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer); -#define MASKPOINT_ISSEL(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) -#define MASKPOINT_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 -#define MASKPOINT_DESEL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 -#define MASKPOINT_INVSEL(p) { (p)->bezt.f1 ^= SELECT; (p)->bezt.f2 ^= SELECT; (p)->bezt.f3 ^= SELECT; } (void)0 +#define MASKPOINT_ISSEL_ANY(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) +#define MASKPOINT_ISSEL_KNOT(p) ( (p)->bezt.f2 & SELECT) +#define MASKPOINT_ISSEL_HANDLE_ONLY(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) && (((p)->bezt.f2 & SELECT) == 0) ) +#define MASKPOINT_ISSEL_HANDLE(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) ) -#define MASKPOINT_CV_ISSEL(p) ( (p)->bezt.f2 & SELECT) +#define MASKPOINT_SEL_ALL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 +#define MASKPOINT_DESEL_ALL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 +#define MASKPOINT_INVSEL_ALL(p) { (p)->bezt.f1 ^= SELECT; (p)->bezt.f2 ^= SELECT; (p)->bezt.f3 ^= SELECT; } (void)0 -#define MASKPOINT_HANDLE_ONLY_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) && (((p)->bezt.f2 & SELECT) == 0) ) -#define MASKPOINT_HANDLE_ISSEL(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) ) -#define MASKPOINT_HANDLE_SEL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 -#define MASKPOINT_HANDLE_DESEL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 +#define MASKPOINT_SEL_HANDLE(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 +#define MASKPOINT_DESEL_HANDLE(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 #endif diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index ce62b9c10dc..84ac51f68ae 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -3200,8 +3200,7 @@ float (*BKE_curve_vertexCos_get(Curve * UNUSED(cu), ListBase * lb, int *numVerts else { BPoint *bp = nu->bp; - for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { - copy_v3_v3(co, bp->vec); co += 3; + for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { copy_v3_v3(co, bp->vec); co += 3; } } } diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 1e2d65c4dd7..3421f5ad9e5 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -655,10 +655,10 @@ void BKE_mask_point_select_set(MaskSplinePoint *point, int select) int i; if (select) { - MASKPOINT_SEL(point); + MASKPOINT_SEL_ALL(point); } else { - MASKPOINT_DESEL(point); + MASKPOINT_DESEL_ALL(point); } for (i = 0; i < point->tot_uw; i++) { @@ -674,10 +674,10 @@ void BKE_mask_point_select_set(MaskSplinePoint *point, int select) void BKE_mask_point_select_set_handle(MaskSplinePoint *point, int select) { if (select) { - MASKPOINT_HANDLE_SEL(point); + MASKPOINT_SEL_HANDLE(point); } else { - MASKPOINT_HANDLE_DESEL(point); + MASKPOINT_DESEL_HANDLE(point); } } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index ae64294fd3e..0cf2cb77177 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -124,7 +124,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) int sel = FALSE; if (j == 0) { - sel = MASKPOINT_ISSEL(point); + sel = MASKPOINT_ISSEL_ANY(point); } else { sel = point->uw[j - 1].flag & SELECT; @@ -174,7 +174,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) } /* draw CV point */ - if (MASKPOINT_CV_ISSEL(point)) { + if (MASKPOINT_ISSEL_KNOT(point)) { if (point == maskobj->act_point) glColor3f(1.0f, 1.0f, 1.0f); else @@ -189,7 +189,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) /* draw handle points */ if (has_handle) { - if (MASKPOINT_HANDLE_ISSEL(point)) { + if (MASKPOINT_ISSEL_HANDLE(point)) { if (point == maskobj->act_point) glColor3f(1.0f, 1.0f, 1.0f); else diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 5e547d9dec4..c5371e7760a 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -660,7 +660,7 @@ static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) ED_mask_select_flush_all(mask); } } - else if (!MASKPOINT_ISSEL(slidedata->point)) { + else if (!MASKPOINT_ISSEL_ANY(slidedata->point)) { ED_mask_select_toggle_all(mask, SEL_DESELECT); BKE_mask_point_select_set(slidedata->point, TRUE); @@ -963,7 +963,7 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask BKE_mask_parent_init(&new_point->parent); /* select new point */ - MASKPOINT_SEL(new_point); + MASKPOINT_SEL_ALL(new_point); ED_mask_select_flush_all(mask); } @@ -1040,7 +1040,7 @@ static void finSelectedSplinePoint(MaskObject *maskobj, MaskSpline **spline, Mas for (i = 0; i < cur_spline->tot_point; i++) { MaskSplinePoint *cur_point = &cur_spline->points[i]; - if (MASKPOINT_ISSEL(cur_point)) { + if (MASKPOINT_ISSEL_ANY(cur_point)) { if (*spline != NULL && *spline != cur_spline) { *spline = NULL; *point = NULL; @@ -1088,7 +1088,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, const float co[2]) point_index = (point - spline->points); - MASKPOINT_DESEL(point); + MASKPOINT_DESEL_ALL(point); if ((spline->flag & MASK_SPLINE_CYCLIC) || (point_index > 0 && point_index != spline->tot_point - 1)) @@ -1222,7 +1222,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "location", co); - if (maskobj && maskobj->act_point && MASKPOINT_ISSEL(maskobj->act_point)) { + if (maskobj && maskobj->act_point && MASKPOINT_ISSEL_ANY(maskobj->act_point)) { /* cheap trick - double click for cyclic */ MaskSpline *spline = maskobj->act_spline; @@ -1469,7 +1469,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - if (!MASKPOINT_ISSEL(point)) + if (!MASKPOINT_ISSEL_ANY(point)) count++; } @@ -1495,7 +1495,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) for (i = 0, j = 0; i < tot_point_orig; i++) { MaskSplinePoint *point = &spline->points[i]; - if (!MASKPOINT_ISSEL(point)) { + if (!MASKPOINT_ISSEL_ANY(point)) { if (point == maskobj->act_point) maskobj->act_point = &new_points[j]; @@ -1571,7 +1571,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - if (MASKPOINT_ISSEL(point)) { + if (MASKPOINT_ISSEL_ANY(point)) { BezTriple *bezt = &point->bezt; bezt->h1 = bezt->h2 = handle_type; diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 2d2c527d961..65c3980e3ea 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -74,7 +74,7 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - if (MASKPOINT_ISSEL(point)) { + if (MASKPOINT_ISSEL_ANY(point)) { point->parent.flag &= ~MASK_PARENT_ACTIVE; } } @@ -144,7 +144,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - if (MASKPOINT_ISSEL(point)) { + if (MASKPOINT_ISSEL_ANY(point)) { point->parent.id_type = ID_MC; point->parent.id = &clip->id; strcpy(point->parent.parent, tracking->name); diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 679f25aafea..4f0b33294d3 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -64,7 +64,7 @@ int ED_mask_spline_select_check(MaskSplinePoint *points, int tot_point) for (i = 0; i < tot_point; i++) { MaskSplinePoint *point = &points[i]; - if (MASKPOINT_ISSEL(point)) + if (MASKPOINT_ISSEL_ANY(point)) return TRUE; } @@ -159,7 +159,7 @@ void ED_mask_select_flush_all(Mask *mask) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *cur_point = &spline->points[i]; - if (MASKPOINT_ISSEL(cur_point)) { + if (MASKPOINT_ISSEL_ANY(cur_point)) { spline->flag |= SELECT; } else { @@ -248,7 +248,7 @@ static int select_exec(bContext *C, wmOperator *op) maskobj->act_spline = spline; maskobj->act_point = point; - if (!MASKPOINT_HANDLE_ISSEL(point)) { + if (!MASKPOINT_ISSEL_HANDLE(point)) { BKE_mask_point_select_set_handle(point, TRUE); } else if (toggle) { @@ -270,7 +270,7 @@ static int select_exec(bContext *C, wmOperator *op) maskobj->act_spline = spline; maskobj->act_point = point; - if (!MASKPOINT_ISSEL(point)) { + if (!MASKPOINT_ISSEL_ANY(point)) { BKE_mask_point_select_set(point, TRUE); } else if (toggle) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f563a7a089d..89228423bf5 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5890,7 +5890,7 @@ static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, { BezTriple *bezt = &point->bezt; float aspx, aspy; - short is_sel_point = MASKPOINT_ISSEL(point); + short is_sel_point = MASKPOINT_ISSEL_ANY(point); tdm->point = point; copy_m3_m3(tdm->vec, bezt->vec); @@ -5994,8 +5994,8 @@ static void createTransMaskingData(bContext *C, TransInfo *t) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - if (MASKPOINT_ISSEL(point)) { - if (MASKPOINT_CV_ISSEL(point)) + if (MASKPOINT_ISSEL_ANY(point)) { + if (MASKPOINT_ISSEL_KNOT(point)) countsel += 3; else countsel += 1; @@ -6033,10 +6033,10 @@ static void createTransMaskingData(bContext *C, TransInfo *t) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - if (propmode || MASKPOINT_ISSEL(point)) { + if (propmode || MASKPOINT_ISSEL_ANY(point)) { MaskPointToTransData(sc, point, td, td2d, tdm, propmode); - if (propmode || MASKPOINT_CV_ISSEL(point)) { + if (propmode || MASKPOINT_ISSEL_KNOT(point)) { td += 3; td2d += 3; tdm += 3; From 44806d2c2bfceb061f90dc9ab0795e9e7d57869b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 12:08:08 +0000 Subject: [PATCH 114/183] fix for mask transform in non proportional mode. --- source/blender/editors/transform/transform_conversions.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 89228423bf5..d00539ff43c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5890,7 +5890,8 @@ static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, { BezTriple *bezt = &point->bezt; float aspx, aspy; - short is_sel_point = MASKPOINT_ISSEL_ANY(point); + short is_sel_point = MASKPOINT_ISSEL_KNOT(point); + short is_sel_any = MASKPOINT_ISSEL_ANY(point); tdm->point = point; copy_m3_m3(tdm->vec, bezt->vec); @@ -5920,7 +5921,7 @@ static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, td->ext= NULL; td->val= NULL; - if (is_sel_point) { + if (is_sel_any) { td->flag |= TD_SELECTED; } td->dist= 0.0; @@ -5955,7 +5956,7 @@ static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, td->ext= NULL; td->val= NULL; - if (is_sel_point) { + if (is_sel_any) { td->flag |= TD_SELECTED; } From ba7606db15f5ee87186269e311cdef3022a5e797 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 12:54:50 +0000 Subject: [PATCH 115/183] impliment restrict select option. --- .../editors/interface/interface_templates.c | 5 +-- source/blender/editors/mask/mask_draw.c | 10 +++--- source/blender/editors/mask/mask_ops.c | 33 +++++++++---------- .../blender/editors/mask/mask_relationships.c | 4 +-- source/blender/editors/mask/mask_select.c | 16 +++++++-- source/blender/editors/mask/mask_shapekey.c | 4 +-- .../editors/transform/transform_conversions.c | 4 +-- 7 files changed, 44 insertions(+), 32 deletions(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 54b87fd4509..1acfefe8a4c 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2242,14 +2242,15 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe } } else if (itemptr->type == &RNA_MaskObject) { - split = uiLayoutSplit(sub, 0.5f, 0); + split = uiLayoutSplit(sub, 0.66f, 0); uiItemL(split, name, icon); uiBlockSetEmboss(block, UI_EMBOSSN); row = uiLayoutRow(split, 1); - uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE); + // uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE); // enable when used uiItemR(row, itemptr, "hide", 0, "", 0); + uiItemR(row, itemptr, "hide_select", 0, "", 0); uiBlockSetEmboss(block, UI_EMBOSS); } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 0cf2cb77177..ef1dee3f2fe 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -51,7 +51,7 @@ static void set_spline_color(MaskObject *maskobj, MaskSpline *spline) { - if (spline->flag & SELECT) { + if ((spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0) { if (maskobj->act_spline == spline) glColor3f(1.0f, 1.0f, 1.0f); else @@ -246,7 +246,7 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline) feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_feather_point); /* draw feather */ - if (spline->flag & SELECT) + if ((spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0) glColor3f(0.0f, 1.0f, 0.0f); else glColor3f(0.0f, 0.5f, 0.0f); @@ -278,8 +278,10 @@ static void draw_maskobjs(Mask *mask) // draw_spline_parents(maskobj, spline); - /* ...and then handles over the curve so they're nicely visible */ - draw_spline_points(maskobj, spline); + if (!(maskobj->restrictflag & MASK_RESTRICT_SELECT)) { + /* ...and then handles over the curve so they're nicely visible */ + draw_spline_points(maskobj, spline); + } /* show undeform for testing */ if (0) { diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index c5371e7760a..a2e634bdeba 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -143,7 +143,7 @@ MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float norma for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -245,7 +245,7 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in int i, tot_feather_point; float *feather_points, *fp; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -336,7 +336,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -1060,9 +1060,8 @@ static void finSelectedSplinePoint(MaskObject *maskobj, MaskSpline **spline, Mas } } -static int add_vertex_extrude(bContext *C, Mask *mask, const float co[2]) +static int add_vertex_extrude(bContext *C, Mask *mask, MaskObject *maskobj, const float co[2]) { - MaskObject *maskobj; MaskSpline *spline; MaskSplinePoint *point; MaskSplinePoint *new_point = NULL, *ref_point = NULL; @@ -1077,8 +1076,6 @@ static int add_vertex_extrude(bContext *C, Mask *mask, const float co[2]) ED_mask_select_toggle_all(mask, SEL_DESELECT); - maskobj = BKE_mask_object_active(mask); - if (!maskobj) { return FALSE; } @@ -1163,17 +1160,14 @@ static int add_vertex_extrude(bContext *C, Mask *mask, const float co[2]) return TRUE; } -static int add_vertex_new(bContext *C, Mask *mask, const float co[2]) +static int add_vertex_new(bContext *C, Mask *mask, MaskObject *maskobj, const float co[2]) { - MaskObject *maskobj; MaskSpline *spline; MaskSplinePoint *point; MaskSplinePoint *new_point = NULL, *ref_point = NULL; ED_mask_select_toggle_all(mask, SEL_DESELECT); - maskobj = BKE_mask_object_active(mask); - if (!maskobj) { /* if there's no maskobj currently operationg on, create new one */ maskobj = BKE_mask_object_new(mask, ""); @@ -1216,7 +1210,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) maskobj = BKE_mask_object_active(mask); - if (maskobj && maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { maskobj = NULL; } @@ -1255,14 +1249,14 @@ static int add_vertex_exec(bContext *C, wmOperator *op) } if (!add_vertex_subdivide(C, mask, co)) { - if (!add_vertex_extrude(C, mask, co)) { + if (!add_vertex_extrude(C, mask, maskobj, co)) { return OPERATOR_CANCELLED; } } } else { if (!add_vertex_subdivide(C, mask, co)) { - if (!add_vertex_new(C, mask, co)) { + if (!add_vertex_new(C, mask, maskobj, co)) { return OPERATOR_CANCELLED; } } @@ -1376,7 +1370,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -1454,7 +1448,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -1563,7 +1557,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) MaskSpline *spline; int i; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -1664,6 +1658,11 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) int changed = FALSE; for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + + if (maskobj->restrictflag & MASK_RESTRICT_SELECT) { + continue; + } + if (!unselected) { if (ED_mask_object_select_check(maskobj)) { ED_mask_object_select_set(maskobj, FALSE); diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 65c3980e3ea..c799ca1e071 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -66,7 +66,7 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) MaskSpline *spline; int i; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -136,7 +136,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) MaskSpline *spline; int i; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 4f0b33294d3..05dad9f380f 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -75,6 +75,10 @@ int ED_mask_object_select_check(MaskObject *maskobj) { MaskSpline *spline; + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + return FALSE; + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { return TRUE; @@ -101,6 +105,12 @@ void ED_mask_object_select_set(MaskObject *maskobj, int select) { MaskSpline *spline; + if (maskobj->restrictflag & MASK_RESTRICT_SELECT) { + if (select == TRUE) { + return; + } + } + for (spline = maskobj->splines.first; spline; spline = spline->next) { int i; @@ -375,7 +385,7 @@ static int border_select_exec(bContext *C, wmOperator *op) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -447,7 +457,7 @@ static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -573,7 +583,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 71b10ae0da3..cf2fb71920b 100755 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -67,7 +67,7 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op)) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskObjectShape *maskobj_shape; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -113,7 +113,7 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskObjectShape *maskobj_shape; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index d00539ff43c..8211df67b17 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5985,7 +5985,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline = maskobj->splines.first; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -6024,7 +6024,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline = maskobj->splines.first; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } From 6340a10cc590187bc105c171288e3e07b7bfbccd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 13:21:13 +0000 Subject: [PATCH 116/183] fix for own mistake --- source/blender/editors/mask/mask_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index a2e634bdeba..e06342090c2 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1210,7 +1210,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) maskobj = BKE_mask_object_active(mask); - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (maskobj && maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { maskobj = NULL; } From b6950f42b6bfdef3cb9e90872d6564000e5a6c41 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 13:46:44 +0000 Subject: [PATCH 117/183] only keyframe selected maskobjects --- source/blender/editors/mask/mask_shapekey.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index cf2fb71920b..e323a6abe15 100755 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -67,7 +67,7 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op)) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskObjectShape *maskobj_shape; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (!ED_mask_object_select_check(maskobj)) { continue; } @@ -113,7 +113,7 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskObjectShape *maskobj_shape; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (!ED_mask_object_select_check(maskobj)) { continue; } From 4a71d2e86cad5f7371328149c2663390b3ac7975 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 30 May 2012 14:30:28 +0000 Subject: [PATCH 118/183] Fixed crash of mask node when mask is not set --- .../operations/COM_MaskOperation.cpp | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index e6456e73be3..a742306f440 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -65,6 +65,9 @@ void *MaskOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers if (this->rasterizedMask) return this->rasterizedMask; + if (!this->mask) + return NULL; + BLI_mutex_lock(getMutex()); if (this->rasterizedMask == NULL) { int width = this->getWidth(); @@ -101,13 +104,21 @@ void MaskOperation::determineResolution(unsigned int resolution[], unsigned int void MaskOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) { - float *buffer = (float*) data; - int index = (y * this->getWidth() + x); + if (!data) { + color[0] = 0; + color[1] = 0; + color[2] = 0; + color[3] = 1.0f; + } + else { + float *buffer = (float*) data; + int index = (y * this->getWidth() + x); - color[0] = buffer[index]; - color[1] = buffer[index]; - color[2] = buffer[index]; - color[3] = 1.0f; + color[0] = buffer[index]; + color[1] = buffer[index]; + color[2] = buffer[index]; + color[3] = 1.0f; + } } From 6fb53f7c4207240805fa9fc6d3d2f406bb3ef474 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 30 May 2012 14:39:20 +0000 Subject: [PATCH 119/183] Several small fixes to nodes: - Code formation fix in keying node - Fixed crash when creating keying screen for frame where there's no movie - Attempt to improve keying node to handle alpha on hair better --- .../blender/compositor/operations/COM_KeyingOperation.cpp | 8 ++++---- .../compositor/operations/COM_KeyingScreenOperation.cpp | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp index 43348568a5d..5f1c9d0640d 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp @@ -47,7 +47,7 @@ static float get_pixel_saturation(float *pixel, float screen_balance) float mid = pixel[0] + pixel[1] + pixel[2] - min - max; float val = (1.0f - screen_balance) * min + screen_balance * mid; - return max - val; + return (max - val) * (1.0f - val) * (1.0f - val); } KeyingOperation::KeyingOperation(): NodeOperation() @@ -92,7 +92,7 @@ void KeyingOperation::executePixel(float *color, float x, float y, PixelSampler if (primary_channel != screen_primary_channel) { /* different main channel means pixel is on foreground */ color[0] = 1.0f; - } + } else if (saturation >= screen_saturation) { /* saturation of main channel is more than screen, definitely a background */ color[0] = 0.0f; @@ -102,7 +102,7 @@ void KeyingOperation::executePixel(float *color, float x, float y, PixelSampler distance = 1.0f - saturation / screen_saturation; - color[0] = distance; + color[0] = distance * distance; if (color[0] < this->clipBlack) color[0] = 0.0f; @@ -110,5 +110,5 @@ void KeyingOperation::executePixel(float *color, float x, float y, PixelSampler color[0] = 1.0f; else color[0] = (color[0] - this->clipBlack) / (this->clipWhite - this->clipBlack); - } + } } diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index 456ab31db24..f9c9216b75a 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -102,11 +102,14 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri if (!sites_total) return NULL; - triangulation = (TriangulationData *) MEM_callocN(sizeof(TriangulationData), "keying screen triangulation data"); - BKE_movieclip_user_set_frame(&user, framenumber); ibuf = BKE_movieclip_get_ibuf(movieClip, &user); + if (!ibuf) + return NULL; + + triangulation = (TriangulationData *) MEM_callocN(sizeof(TriangulationData), "keying screen triangulation data"); + sites = (VoronoiSite *) MEM_callocN(sizeof(VoronoiSite) * sites_total, "keyingscreen voronoi sites"); track = (MovieTrackingTrack *) tracksbase->first; i = 0; From 001ea9fc9f5229394847a1cc0bb6479f6baf0b12 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 15:23:17 +0000 Subject: [PATCH 120/183] minor mask draw code refactor --- source/blender/editors/mask/mask_draw.c | 124 ++++++++++++++++-------- 1 file changed, 85 insertions(+), 39 deletions(-) diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index ef1dee3f2fe..1e405a4851d 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -49,17 +49,39 @@ #include "mask_intern.h" /* own include */ -static void set_spline_color(MaskObject *maskobj, MaskSpline *spline) +static void mask_spline_color_get(MaskObject *maskobj, MaskSpline *spline, const int is_sel, + unsigned char r_rgb[4]) { - if ((spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0) { - if (maskobj->act_spline == spline) - glColor3f(1.0f, 1.0f, 1.0f); - else - glColor3f(1.0f, 0.0f, 0.0f); + if (is_sel) { + if (maskobj->act_spline == spline) { + r_rgb[0] = r_rgb[1] = r_rgb[2] = 255; + } + else { + r_rgb[0] = 255; + r_rgb[1] = r_rgb[2] = 0; + } } else { - glColor3f(0.5f, 0.0f, 0.0f); + r_rgb[0] = 128; + r_rgb[1] = r_rgb[2] = 0; } + + r_rgb[3] = 255; +} + +static void mask_spline_feather_color_get(MaskObject *UNUSED(maskobj), MaskSpline *UNUSED(spline), const int is_sel, + unsigned char r_rgb[4]) +{ + if (is_sel) { + r_rgb[1] = 255; + r_rgb[0] = r_rgb[2] = 0; + } + else { + r_rgb[1] = 128; + r_rgb[0] = r_rgb[2] = 0; + } + + r_rgb[3] = 255; } #if 0 @@ -99,6 +121,8 @@ static void draw_spline_parents(MaskObject *UNUSED(maskobj), MaskSpline *spline) /* return non-zero if spline is selected */ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) { + const int is_spline_sel = (spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0; + unsigned char rgb_spline[4]; MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, hsize, tot_feather_point; @@ -111,6 +135,8 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) glPointSize(hsize); + mask_spline_color_get(maskobj, spline, is_spline_sel, rgb_spline); + /* feather points */ feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); for (i = 0; i < spline->tot_point; i++) { @@ -165,7 +191,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) /* draw handle segment */ if (has_handle) { - set_spline_color(maskobj, spline); + glColor3ubv(rgb_spline); glBegin(GL_LINES); glVertex3fv(vert); @@ -208,33 +234,43 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) glPointSize(1.0f); } -static void draw_spline_curve_lines(const float *points, int tot_point, int closed) +/* #define USE_XOR */ + +static void draw_curve_dashed(MaskSpline *spline, float *points, int tot_point, const unsigned char rgb_sel[4]) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, points); - glDrawArrays(closed ? GL_LINE_LOOP : GL_LINE_STRIP, 0, tot_point); - glDisableClientState(GL_VERTEX_ARRAY); -} + const int draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GL_LINE_LOOP : GL_LINE_STRIP; -static void draw_dashed_curve(MaskSpline *spline, float *points, int tot_point) -{ - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_OR); - - draw_spline_curve_lines(points, tot_point, spline->flag & MASK_SPLINE_CYCLIC); - - glDisable(GL_COLOR_LOGIC_OP); - glLineStipple(3, 0xaaaa); glEnable(GL_LINE_STIPPLE); - glColor3f(0.0f, 0.0f, 0.0f); - draw_spline_curve_lines(points, tot_point, spline->flag & MASK_SPLINE_CYCLIC); +#ifdef USE_XOR + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_OR); +#endif + + glColor4ubv(rgb_sel); + glLineStipple(3, 0xaaaa); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, points); + glDrawArrays(draw_method, 0, tot_point); + +#ifdef USE_XOR + glDisable(GL_COLOR_LOGIC_OP); +#endif + + glColor4ub(0, 0, 0, 255); + glLineStipple(3, 0x5555); + glDrawArrays(draw_method, 0, tot_point); + glDisableClientState(GL_VERTEX_ARRAY); glDisable(GL_LINE_STIPPLE); } -static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline) +static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, + const char use_smooth, const char draw_type) { + unsigned char rgb_tmp[4]; + + const int is_spline_sel = (spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0; float *diff_points, *feather_points; int tot_diff_point, tot_feather_point; @@ -243,24 +279,34 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline) if (!diff_points) return; + if (use_smooth) { + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_feather_point); /* draw feather */ - if ((spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0) - glColor3f(0.0f, 1.0f, 0.0f); - else - glColor3f(0.0f, 0.5f, 0.0f); - draw_dashed_curve(spline, feather_points, tot_feather_point); + mask_spline_feather_color_get(maskobj, spline, is_spline_sel, rgb_tmp); + draw_curve_dashed(spline, feather_points, tot_feather_point, rgb_tmp); + MEM_freeN(feather_points); /* draw main curve */ - set_spline_color(maskobj, spline); - draw_dashed_curve(spline, diff_points, tot_diff_point); - + mask_spline_color_get(maskobj, spline, is_spline_sel, rgb_tmp); + draw_curve_dashed(spline, diff_points, tot_diff_point, rgb_tmp); MEM_freeN(diff_points); - MEM_freeN(feather_points); + + if (use_smooth) { + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + } + + (void)draw_type; } -static void draw_maskobjs(Mask *mask) +static void draw_maskobjs(Mask *mask, + const char use_smooth, const char draw_type) { MaskObject *maskobj; @@ -274,7 +320,7 @@ static void draw_maskobjs(Mask *mask) for (spline = maskobj->splines.first; spline; spline = spline->next) { /* draw curve itself first... */ - draw_spline_curve(maskobj, spline); + draw_spline_curve(maskobj, spline, use_smooth, draw_type); // draw_spline_parents(maskobj, spline); @@ -288,7 +334,7 @@ static void draw_maskobjs(Mask *mask) void *back = spline->points_deform; spline->points_deform = NULL; - draw_spline_curve(maskobj, spline); + draw_spline_curve(maskobj, spline, use_smooth, draw_type); // draw_spline_parents(maskobj, spline); draw_spline_points(maskobj, spline); spline->points_deform = back; @@ -304,5 +350,5 @@ void ED_mask_draw(const bContext *C) if (!mask) return; - draw_maskobjs(mask); + draw_maskobjs(mask, FALSE, 0); } From 125e7550ffd4139eab9c71fd2b5ac41e5c599680 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2012 16:22:33 +0000 Subject: [PATCH 121/183] draw options for mask spline matching the UV view --- release/scripts/startup/bl_ui/space_clip.py | 6 + source/blender/editors/include/ED_mask.h | 2 +- source/blender/editors/mask/mask_draw.c | 117 ++++++++++++++---- .../blender/editors/space_clip/space_clip.c | 2 +- source/blender/makesdna/DNA_mask_types.h | 12 ++ source/blender/makesdna/DNA_space_types.h | 4 + source/blender/makesrna/intern/rna_space.c | 30 +++-- 7 files changed, 136 insertions(+), 37 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 0211ffd0c9f..6815aef56d6 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -711,6 +711,12 @@ class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): col.label(text="Display Aspect Ratio:") row = col.row() row.prop(clip, "display_aspect", text="") + + if sc.mode == 'MASKEDITING': + col = layout.column() + col.prop(sc, "mask_draw_type", text="") + col.prop(sc, "show_mask_smooth") + class CLIP_PT_marker_display(CLIP_PT_clip_view_panel, Panel): diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index ed1d2ba688e..b7dee09cbe9 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -39,7 +39,7 @@ void ED_keymap_mask(struct wmKeyConfig *keyconf); void ED_operatormacros_mask(void); /* mask_draw.c */ -void ED_mask_draw(const bContext *C); +void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type); /* mask_shapekey.c */ int ED_mask_object_shape_auto_key_all(struct Mask *mask, const int frame); diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 1e405a4851d..69c57018ab2 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -236,41 +236,99 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) /* #define USE_XOR */ -static void draw_curve_dashed(MaskSpline *spline, float *points, int tot_point, const unsigned char rgb_sel[4]) +static void mask_draw_curve_type(MaskSpline *spline, float *points, int tot_point, + const short is_feather, const short is_smooth, + const unsigned char rgb_spline[4], const char draw_type) { const int draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GL_LINE_LOOP : GL_LINE_STRIP; + unsigned char rgb_tmp[4]; - glEnable(GL_LINE_STIPPLE); - -#ifdef USE_XOR - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_OR); -#endif - - glColor4ubv(rgb_sel); - glLineStipple(3, 0xaaaa); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, points); - glDrawArrays(draw_method, 0, tot_point); + + switch (draw_type) { + + case MASK_DT_OUTLINE: + glLineWidth(3); + cpack(0x0); + + glDrawArrays(draw_method, 0, tot_point); + + glLineWidth(1); + glColor4ubv(rgb_spline); + glDrawArrays(draw_method, 0, tot_point); + + break; + + case MASK_DT_DASH: + default: + glEnable(GL_LINE_STIPPLE); #ifdef USE_XOR - glDisable(GL_COLOR_LOGIC_OP); + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_OR); #endif + glColor4ubv(rgb_spline); + glLineStipple(3, 0xaaaa); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, points); + glDrawArrays(draw_method, 0, tot_point); + +#ifdef USE_XOR + glDisable(GL_COLOR_LOGIC_OP); +#endif + glColor4ub(0, 0, 0, 255); + glLineStipple(3, 0x5555); + glDrawArrays(draw_method, 0, tot_point); + + glDisable(GL_LINE_STIPPLE); + break; + + + case MASK_DT_BLACK: + case MASK_DT_WHITE: + if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0; } + else { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; } + /* alpha values seem too low but gl draws many points that compensate for it */ + if (is_feather) { rgb_tmp[3] = 64; } + else { rgb_tmp[3] = 128; } + + if (is_feather) { + rgb_tmp[0] = (unsigned char)(((short)rgb_tmp[0] + (short)rgb_spline[0]) / 2); + rgb_tmp[1] = (unsigned char)(((short)rgb_tmp[1] + (short)rgb_spline[1]) / 2); + rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2); + } + + if (is_smooth == FALSE && is_feather) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + glColor4ubv(rgb_tmp); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, points); + glDrawArrays(draw_method, 0, tot_point); + + glDrawArrays(draw_method, 0, tot_point); + + if (is_smooth == FALSE && is_feather) { + glDisable(GL_BLEND); + } + + break; + } - glColor4ub(0, 0, 0, 255); - glLineStipple(3, 0x5555); - glDrawArrays(draw_method, 0, tot_point); glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_LINE_STIPPLE); } static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, - const char use_smooth, const char draw_type) + const char draw_flag, const char draw_type) { unsigned char rgb_tmp[4]; - const int is_spline_sel = (spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0; + const short is_spline_sel = (spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0; + const short is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH); float *diff_points, *feather_points; int tot_diff_point, tot_feather_point; @@ -279,7 +337,7 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, if (!diff_points) return; - if (use_smooth) { + if (is_smooth) { glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -289,15 +347,19 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, /* draw feather */ mask_spline_feather_color_get(maskobj, spline, is_spline_sel, rgb_tmp); - draw_curve_dashed(spline, feather_points, tot_feather_point, rgb_tmp); + mask_draw_curve_type(spline, feather_points, tot_feather_point, + TRUE, is_smooth, + rgb_tmp, draw_type); MEM_freeN(feather_points); /* draw main curve */ mask_spline_color_get(maskobj, spline, is_spline_sel, rgb_tmp); - draw_curve_dashed(spline, diff_points, tot_diff_point, rgb_tmp); + mask_draw_curve_type(spline, diff_points, tot_diff_point, + FALSE, is_smooth, + rgb_tmp, draw_type); MEM_freeN(diff_points); - if (use_smooth) { + if (draw_flag & MASK_DRAWFLAG_SMOOTH) { glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); } @@ -306,7 +368,7 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, } static void draw_maskobjs(Mask *mask, - const char use_smooth, const char draw_type) + const char draw_flag, const char draw_type) { MaskObject *maskobj; @@ -320,7 +382,7 @@ static void draw_maskobjs(Mask *mask, for (spline = maskobj->splines.first; spline; spline = spline->next) { /* draw curve itself first... */ - draw_spline_curve(maskobj, spline, use_smooth, draw_type); + draw_spline_curve(maskobj, spline, draw_flag, draw_type); // draw_spline_parents(maskobj, spline); @@ -334,7 +396,7 @@ static void draw_maskobjs(Mask *mask, void *back = spline->points_deform; spline->points_deform = NULL; - draw_spline_curve(maskobj, spline, use_smooth, draw_type); + draw_spline_curve(maskobj, spline, draw_flag, draw_type); // draw_spline_parents(maskobj, spline); draw_spline_points(maskobj, spline); spline->points_deform = back; @@ -343,12 +405,13 @@ static void draw_maskobjs(Mask *mask, } } -void ED_mask_draw(const bContext *C) +void ED_mask_draw(const bContext *C, + const char draw_flag, const char draw_type) { Mask *mask = CTX_data_edit_mask(C); if (!mask) return; - draw_maskobjs(mask, FALSE, 0); + draw_maskobjs(mask, draw_flag, draw_type); } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 8c5ae38011d..b24db67cfc2 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1136,7 +1136,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) glScalef(maxdim * zoomx, maxdim * zoomy, 0); glMultMatrixf(sc->stabmat); - ED_mask_draw((bContext *)C); + ED_mask_draw((bContext *)C, sc->mask_draw_flag, sc->mask_draw_type); ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 65707725a53..d427e1561cb 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -132,4 +132,16 @@ typedef struct MaskObject { #define MASK_RESTRICT_SELECT 2 #define MASK_RESTRICT_RENDER 4 +/* SpaceClip->mask_draw_flag */ +#define MASK_DRAWFLAG_SMOOTH 1 + +/* copy of eSpaceImage_UVDT */ +/* SpaceClip->mask_draw_type */ +enum { + MASK_DT_OUTLINE = 0, + MASK_DT_DASH, + MASK_DT_BLACK, + MASK_DT_WHITE +}; + #endif // __DNA_MASK_TYPES_H__ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index fe8617079aa..b1e64641985 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1014,6 +1014,10 @@ typedef struct SpaceClip { /* **** mask editing **** */ struct Mask *mask; + /* draw options */ + char mask_draw_flag; + char mask_draw_type; + char pad3[6]; } SpaceClip; /* SpaceClip->flag */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index c6d5ded0b9b..5e1a17b8e1d 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -45,6 +45,7 @@ #include "DNA_object_types.h" #include "DNA_space_types.h" #include "DNA_sequence_types.h" +#include "DNA_mask_types.h" #include "DNA_view3d_types.h" #include "WM_api.h" @@ -1068,6 +1069,14 @@ static void rna_SpaceClipEditor_view_type_update(Main *UNUSED(bmain), Scene *UNU #else +static EnumPropertyItem dt_uv_items[] = { + {SI_UVDT_OUTLINE, "OUTLINE", 0, "Outline", "Draw white edges with black outline"}, + {SI_UVDT_DASH, "DASH", 0, "Dash", "Draw dashed black-white edges"}, + {SI_UVDT_BLACK, "BLACK", 0, "Black", "Draw black edges"}, + {SI_UVDT_WHITE, "WHITE", 0, "White", "Draw white edges"}, + {0, NULL, 0, NULL, NULL} +}; + static void rna_def_space(BlenderRNA *brna) { StructRNA *srna; @@ -1099,14 +1108,6 @@ static void rna_def_space_image_uv(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - static EnumPropertyItem dt_uv_items[] = { - {SI_UVDT_OUTLINE, "OUTLINE", 0, "Outline", "Draw white edges with black outline"}, - {SI_UVDT_DASH, "DASH", 0, "Dash", "Draw dashed black-white edges"}, - {SI_UVDT_BLACK, "BLACK", 0, "Black", "Draw black edges"}, - {SI_UVDT_WHITE, "WHITE", 0, "White", "Draw white edges"}, - {0, NULL, 0, NULL, NULL} - }; - static EnumPropertyItem dt_uvstretch_items[] = { {SI_UVDT_STRETCH_ANGLE, "ANGLE", 0, "Angle", "Angular distortion between UV and 3D angles"}, {SI_UVDT_STRETCH_AREA, "AREA", 0, "Area", "Area distortion between UV and 3D faces"}, @@ -3043,6 +3044,19 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceClipEditor_mask_set", NULL, NULL); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + /* mask drawing */ + prop = RNA_def_property(srna, "mask_draw_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mask_draw_type"); + RNA_def_property_enum_items(prop, dt_uv_items); + RNA_def_property_ui_text(prop, "Edge Draw Type", "Draw type for mask splines"); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + + prop = RNA_def_property(srna, "show_mask_smooth", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mask_draw_flag", MASK_DRAWFLAG_SMOOTH); + RNA_def_property_ui_text(prop, "Draw Smooth Splines", ""); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + + /* mode */ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); From 6f64165b952276e7e251c06a8d3043441e3f4a07 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Wed, 30 May 2012 18:39:42 +0000 Subject: [PATCH 122/183] Mask out of bounds fix for mask rasterizer --- intern/raskter/raskter.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 2cd1b38d525..e68379486e9 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -232,7 +232,7 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. * Will get changed once DEM code gets in. */ - for (y_curr = MAX2(ctx->all_edges->ybeg, 0); (ctx->all_edges || ctx->possible_edges) && (y_curr < ctx->rb.sizey); y_curr++) { + for (y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) { /* * Link any edges that start on the current scan line into the list of @@ -305,12 +305,14 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ e_curr = e_curr->e_next; mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; - /* draw the pixels. */ - for (; cpxl <= mpxl; cpxl++){ - if(*cpxl < 0.5f){ - *cpxl = 1.0f; - }else{ - *cpxl = 0.0f; + if((y_curr >= 0) && (y_curr < ctx->rb.sizey)){ + /* draw the pixels. */ + for (; cpxl <= mpxl; cpxl++){ + if(*cpxl < 0.5f){ + *cpxl = 1.0f; + }else{ + *cpxl = 0.0f; + } } } } From 3795d73235b9b310687ad80744a1db071cc6f193 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Wed, 30 May 2012 21:15:17 +0000 Subject: [PATCH 123/183] Adds property to mask splines to allow them to be negated (black masks), still needs work in tracking.c --- intern/raskter/raskter.c | 12 ++++-------- intern/raskter/raskter.h | 2 +- release/scripts/startup/bl_ui/space_clip.py | 1 + source/blender/blenkernel/intern/mask.c | 2 +- source/blender/blenkernel/intern/tracking.c | 4 ++-- source/blender/makesdna/DNA_mask_types.h | 1 + source/blender/makesrna/intern/rna_mask.c | 7 +++++++ 7 files changed, 17 insertions(+), 12 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index e68379486e9..d4e8c4f4fce 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -171,7 +171,7 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need * if it ends up being coupled with this function. */ -int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts) +int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, float fill_color) { int x_curr; /* current pixel position in X */ int y_curr; /* current scan line being drawn */ @@ -308,11 +308,7 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ if((y_curr >= 0) && (y_curr < ctx->rb.sizey)){ /* draw the pixels. */ for (; cpxl <= mpxl; cpxl++){ - if(*cpxl < 0.5f){ - *cpxl = 1.0f; - }else{ - *cpxl = 0.0f; - } + *cpxl = fill_color; } } } @@ -388,7 +384,7 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ return 1; } -int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { +int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y, float fill_color) { int i; /* i: Loop counter. */ struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ struct r_fill_context ctx = {0}; @@ -421,7 +417,7 @@ int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ - i = rast_scan_fill(&ctx, ply, num); /* Call our rasterizer, passing in the integer coords for each vert. */ + i = rast_scan_fill(&ctx, ply, num, fill_color); /* Call our rasterizer, passing in the integer coords for each vert. */ free(ply); /* Free the memory allocated for the integer coordinate table. */ return(i); /* Return the value returned by the rasterizer. */ } diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h index 98aaf0f6885..e0c256d892a 100644 --- a/intern/raskter/raskter.h +++ b/intern/raskter/raskter.h @@ -48,7 +48,7 @@ struct scan_line_batch { extern "C" { #endif -int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y); +int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y, float fill_color); #ifdef __cplusplus } diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 6815aef56d6..7ed08d16139 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -618,6 +618,7 @@ class CLIP_PT_active_mask_spline(Panel): col = layout.column() col.prop(spline, "weight_interpolation") col.prop(spline, "use_cyclic") + col.prop(spline, "mask_negate") class CLIP_PT_active_mask_point(Panel): diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 3421f5ad9e5..76ff7158b8f 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1754,7 +1754,7 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) } if (tot_diff_point) { - PLX_raskterize(diff_points, tot_diff_point, buffer, width, height); + PLX_raskterize(diff_points, tot_diff_point, buffer, width, height, (spline->flag & MASK_SPLINE_NEGATE)?0.0f:1.0f); MEM_freeN(diff_points); } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 8df6e4c3748..acc0a8636ff 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1322,8 +1322,8 @@ static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTra fp[0] = stroke_points[i].x * width / ibuf->x - marker->search_min[0]; fp[1] = stroke_points[i].y * height * aspy / ibuf->x - marker->search_min[1]; } - - PLX_raskterize(mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y); + /* TODO: not sure best method to get spline->flag here... to tell if mask is negative color */ + PLX_raskterize(mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y, /* TODO: this is color */ 1.0f); MEM_freeN(mask_points); } diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index d427e1561cb..680da5fc82e 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -120,6 +120,7 @@ typedef struct MaskObject { /* MaskSpline->flag */ /* reserve (1 << 0) for SELECT */ #define MASK_SPLINE_CYCLIC (1 << 1) +#define MASK_SPLINE_NEGATE (1 << 2) /* MaskSpline->weight_interp */ #define MASK_SPLINE_INTERP_LINEAR 1 diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 393ca5f3244..dc6d41b5626 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -506,6 +506,13 @@ static void rna_def_maskSpline(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_SPLINE_CYCLIC); RNA_def_property_ui_text(prop, "Cyclic", "Make this spline a closed loop"); RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* negative mask? */ + prop = RNA_def_property(srna, "mask_negate", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_SPLINE_NEGATE); + RNA_def_property_ui_text(prop, "Negate", "Make this spline subtract from mask"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); } static void rna_def_mask_object(BlenderRNA *brna) From 1541c5f6d0de35bfc7083059d6d965fc41de757d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 07:55:04 +0000 Subject: [PATCH 124/183] fix for own mistake --- source/blender/blenkernel/intern/curve.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 84ac51f68ae..ce62b9c10dc 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -3200,7 +3200,8 @@ float (*BKE_curve_vertexCos_get(Curve * UNUSED(cu), ListBase * lb, int *numVerts else { BPoint *bp = nu->bp; - for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { copy_v3_v3(co, bp->vec); co += 3; + for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { + copy_v3_v3(co, bp->vec); co += 3; } } } From d74200a3af286e82b6a262c6cf14157be38e1b58 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 08:24:53 +0000 Subject: [PATCH 125/183] svn merge -r47246:47245 . --- revert 47246, this needs more considersation and planning to do this well --- intern/raskter/raskter.c | 12 ++++++++---- intern/raskter/raskter.h | 2 +- release/scripts/startup/bl_ui/space_clip.py | 1 - source/blender/blenkernel/intern/mask.c | 2 +- source/blender/blenkernel/intern/tracking.c | 4 ++-- source/blender/makesdna/DNA_mask_types.h | 1 - source/blender/makesrna/intern/rna_mask.c | 7 ------- 7 files changed, 12 insertions(+), 17 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index d4e8c4f4fce..e68379486e9 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -171,7 +171,7 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need * if it ends up being coupled with this function. */ -int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, float fill_color) +int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts) { int x_curr; /* current pixel position in X */ int y_curr; /* current scan line being drawn */ @@ -308,7 +308,11 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ if((y_curr >= 0) && (y_curr < ctx->rb.sizey)){ /* draw the pixels. */ for (; cpxl <= mpxl; cpxl++){ - *cpxl = fill_color; + if(*cpxl < 0.5f){ + *cpxl = 1.0f; + }else{ + *cpxl = 0.0f; + } } } } @@ -384,7 +388,7 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ return 1; } -int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y, float fill_color) { +int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { int i; /* i: Loop counter. */ struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ struct r_fill_context ctx = {0}; @@ -417,7 +421,7 @@ int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y, floa ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ - i = rast_scan_fill(&ctx, ply, num, fill_color); /* Call our rasterizer, passing in the integer coords for each vert. */ + i = rast_scan_fill(&ctx, ply, num); /* Call our rasterizer, passing in the integer coords for each vert. */ free(ply); /* Free the memory allocated for the integer coordinate table. */ return(i); /* Return the value returned by the rasterizer. */ } diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h index e0c256d892a..98aaf0f6885 100644 --- a/intern/raskter/raskter.h +++ b/intern/raskter/raskter.h @@ -48,7 +48,7 @@ struct scan_line_batch { extern "C" { #endif -int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y, float fill_color); +int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y); #ifdef __cplusplus } diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 7ed08d16139..6815aef56d6 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -618,7 +618,6 @@ class CLIP_PT_active_mask_spline(Panel): col = layout.column() col.prop(spline, "weight_interpolation") col.prop(spline, "use_cyclic") - col.prop(spline, "mask_negate") class CLIP_PT_active_mask_point(Panel): diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 76ff7158b8f..3421f5ad9e5 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1754,7 +1754,7 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) } if (tot_diff_point) { - PLX_raskterize(diff_points, tot_diff_point, buffer, width, height, (spline->flag & MASK_SPLINE_NEGATE)?0.0f:1.0f); + PLX_raskterize(diff_points, tot_diff_point, buffer, width, height); MEM_freeN(diff_points); } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index acc0a8636ff..8df6e4c3748 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1322,8 +1322,8 @@ static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTra fp[0] = stroke_points[i].x * width / ibuf->x - marker->search_min[0]; fp[1] = stroke_points[i].y * height * aspy / ibuf->x - marker->search_min[1]; } - /* TODO: not sure best method to get spline->flag here... to tell if mask is negative color */ - PLX_raskterize(mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y, /* TODO: this is color */ 1.0f); + + PLX_raskterize(mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y); MEM_freeN(mask_points); } diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 680da5fc82e..d427e1561cb 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -120,7 +120,6 @@ typedef struct MaskObject { /* MaskSpline->flag */ /* reserve (1 << 0) for SELECT */ #define MASK_SPLINE_CYCLIC (1 << 1) -#define MASK_SPLINE_NEGATE (1 << 2) /* MaskSpline->weight_interp */ #define MASK_SPLINE_INTERP_LINEAR 1 diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index dc6d41b5626..393ca5f3244 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -506,13 +506,6 @@ static void rna_def_maskSpline(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_SPLINE_CYCLIC); RNA_def_property_ui_text(prop, "Cyclic", "Make this spline a closed loop"); RNA_def_property_update(prop, 0, "rna_Mask_update_data"); - - /* negative mask? */ - prop = RNA_def_property(srna, "mask_negate", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_SPLINE_NEGATE); - RNA_def_property_ui_text(prop, "Negate", "Make this spline subtract from mask"); - RNA_def_property_update(prop, 0, "rna_Mask_update_data"); } static void rna_def_mask_object(BlenderRNA *brna) From 9aaaa7eeadae7deb8026fb6808fb32a9ae824811 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 31 May 2012 08:38:50 +0000 Subject: [PATCH 126/183] No need in +x flag for mask_shapekey.c --- source/blender/editors/mask/mask_shapekey.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 source/blender/editors/mask/mask_shapekey.c diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c old mode 100755 new mode 100644 From 1308cad23406f24f8c7f1f1bcfe5575a6aa3a4fb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 08:39:22 +0000 Subject: [PATCH 127/183] patch from pete larabell - feather support for masking. --- intern/raskter/raskter.c | 359 +++++++++++++++++++- intern/raskter/raskter.h | 7 +- source/blender/blenkernel/intern/mask.c | 19 +- source/blender/blenkernel/intern/tracking.c | 2 +- 4 files changed, 375 insertions(+), 12 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index e68379486e9..c0da97ddbd5 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -388,19 +388,20 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ return 1; } -int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { +int PLX_raskterize(float (*base_verts)[2], int num_base_verts, float *buf, int buf_x, int buf_y) +{ int i; /* i: Loop counter. */ struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ struct r_fill_context ctx = {0}; /* * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert - * data structure multiplied by the number of verts. + * data structure multiplied by the number of base_verts. * * In the event of a failure to allocate the memory, return 0, so this error can * be distinguished as a memory allocation error. */ - if ((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num))) == NULL) { + if ((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_base_verts))) == NULL) { return(0); } @@ -412,17 +413,357 @@ int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) { * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel * drawn will be 1.0f in value, there is no anti-aliasing. */ - for (i = 0; i < num; i++) { /* Loop over all verts. */ - ply[i].x = (verts[i << 1] * buf_x) + 0.5f; /* Range expand normalized X to integer buffer-space X. */ - ply[i].y = (verts[(i << 1) + 1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */ + for (i = 0; i < num_base_verts; i++) { /* Loop over all base_verts. */ + ply[i].x = (base_verts[i][0] * buf_x) + 0.5f; /* Range expand normalized X to integer buffer-space X. */ + ply[i].y = (base_verts[i][1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */ } ctx.rb.buf = buf; /* Set the output buffer pointer. */ ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ - i = rast_scan_fill(&ctx, ply, num); /* Call our rasterizer, passing in the integer coords for each vert. */ - free(ply); /* Free the memory allocated for the integer coordinate table. */ - return(i); /* Return the value returned by the rasterizer. */ + i = rast_scan_fill(&ctx, ply, num_base_verts); /* Call our rasterizer, passing in the integer coords for each vert. */ + free(ply); /* Free the memory allocated for the integer coordinate table. */ + return(i); /* Return the value returned by the rasterizer. */ } +/* + * This function clips drawing to the frame buffer. That clipping will likely be moved into the preprocessor + * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need + * if it ends up being coupled with this function. + */ +int rast_scan_feather(struct r_fill_context *ctx, + struct poly_vert *base_verts, int num_base_verts, + struct poly_vert *feather_verts, int num_feather_verts) +{ + int x_curr; /* current pixel position in X */ + int y_curr; /* current scan line being drawn */ + int yp; /* y-pixel's position in frame buffer */ + int swixd = 0; /* whether or not edges switched position in X */ + float *cpxl; /* pixel pointers... */ + float *mpxl; + float *spxl; + struct e_status *e_curr; /* edge pointers... */ + struct e_status *e_temp; + struct e_status *edgbuf; + struct e_status **edgec; + + /* from dem */ + int a; // a = temporary pixel index buffer loop counter + int fsz; // size of the frame + unsigned int rsl; // long used for finding fast 1.0/sqrt + float rsf; // float used for finding fast 1.0/sqrt + const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt + + //unsigned int gradientFillOffset; + unsigned int t; + unsigned int ud; // ud = unscaled edge distance + unsigned int dmin; // dmin = minimun edge distance + float odist; // odist = current outer edge distance + float idist; // idist = current inner edge distance + int dx; // dx = X-delta (used for distance proportion calculation) + int dy; // dy = Y-delta (used for distance proportion calculation) + + + /* + * If the number of verts specified to render as a polygon is less than 3, + * return immediately. Obviously we cant render a poly with sides < 3. The + * return for this we set to 1, simply so it can be distinguished from the + * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter + * which is a failure to allocate memory. + */ + if (num_feather_verts < 3) { + return(1); + } + + /* + * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data + * multiplied by the number of edges, which is always equal to the number of verts in + * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for + * the preceeding error, which was a rasterization request on a 2D poly with less than + * 3 sides. + */ + if ((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_feather_verts))) == NULL) { + return(0); + } + + /* + * Do some preprocessing on all edges. This constructs a table structure in memory of all + * the edge properties and can "flip" some edges so sorting works correctly. + */ + preprocess_all_edges(ctx, feather_verts, num_feather_verts, edgbuf); + + /* + * Set the pointer for tracking the edges currently in processing to NULL to make sure + * we don't get some crazy value after initialization. + */ + ctx->possible_edges = NULL; + + /* + * Loop through all scan lines to be drawn. Since we sorted by Y values during + * preprocess_all_edges(), we can already exact values for the lowest and + * highest Y values we could possibly need by induction. The preprocessing sorted + * out edges by Y position, we can cycle the current edge being processed once + * it runs out of Y pixels. When we have no more edges, meaning the current edge + * is NULL after setting the "current" edge to be the previous current edge's + * "next" edge in the Y sorted edge connection chain, we can stop looping Y values, + * since we can't possibly have more scan lines if we ran out of edges. :) + * + * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. + * Will get changed once DEM code gets in. + */ + for (y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) { + + /* + * Link any edges that start on the current scan line into the list of + * edges currently needed to draw at least this, if not several, scan lines. + */ + + /* + * Set the current edge to the beginning of the list of edges to be rasterized + * into this scan line. + * + * We could have lots of edge here, so iterate over all the edges needed. The + * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting + * so we safely cycle edges to thier own "next" edges in order. + * + * At each iteration, make sure we still have a non-NULL edge. + */ + for (edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr); ) { + x_curr = ctx->all_edges->x; /* Set current X position. */ + for (;; ) { /* Start looping edges. Will break when edges run out. */ + e_curr = *edgec; /* Set up a current edge pointer. */ + if (!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ + e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */ + *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */ + ctx->all_edges->e_next = e_curr; /* Set up the next edge. */ + edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */ + ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ + break; /* Stop looping edges (since we ran out or hit empty X span. */ + } + else { + edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ + } + } + } + + /* + * Determine the current scan line's offset in the pixel buffer based on its Y position. + * Basically we just multiply the current scan line's Y value by the number of pixels in each line. + */ + yp = y_curr * ctx->rb.sizex; + /* + * Set a "scan line pointer" in memory. The location of the buffer plus the row offset. + */ + spxl = ctx->rb.buf + (yp); + /* + * Set up the current edge to the first (in X) edge. The edges which could possibly be in this + * list were determined in the preceeding edge loop above. They were already sorted in X by the + * initial processing function. + * + * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge + * we will eventually hit a NULL when the list runs out. + */ + for (e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) { + /* + * Calculate a span of pixels to fill on the current scan line. + * + * Set the current pixel pointer by adding the X offset to the scan line's start offset. + * Cycle the current edge the next edge. + * Set the max X value to draw to be one less than the next edge's first pixel. This way we are + * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than + * one time because it's on a vertex connecting two edges) + * + * Then blast through all the pixels in the span, advancing the pointer and setting the color to white. + * + * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, + * but for now it is done here until the DEM code comes in. + */ + + /* set up xmin and xmax bounds on this scan line */ + cpxl = spxl + MAX2(e_curr->x, 0); + e_curr = e_curr->e_next; + mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; + + if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { + /* draw the pixels. */ + for (; cpxl <= mpxl; cpxl++) { + //do feather check + // first check that pixel isn't already full, and only operate if it is not + if (*cpxl < 0.9999f) { +/* + * Begin modified code from double edge mask compo node... + */ + t = (cpxl - spxl) % ctx->rb.sizex; // calculate column of pixel + + fsz = y_curr; // calculate row of pixel + + + dmin = 0xffffffff; // reset min distance to edge pixel + for (a = 0; a < num_feather_verts; a++) { // loop through all outer edge buffer pixels + dy = t - feather_verts[a].x; // set dx to gradient pixel column - outer edge pixel row + dx = fsz - feather_verts[a].y; // set dy to gradient pixel row - outer edge pixel column + ud = dx * dx + dy * dy; // compute sum of squares + if (ud < dmin) { // if our new sum of squares is less than the current minimum + dmin = ud; // set a new minimum equal to the new lower value + } + } + odist = (float)(dmin); // cast outer min to a float + rsf = odist * 0.5f; // + rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored + rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate + odist = *(float *)&rsl; // reciprocal square root + odist = odist * (rsopf - (rsf * odist * odist)); // -- ** this line can be iterated for more accuracy ** -- + dmin = 0xffffffff; // reset min distance to edge pixel + for (a = 0; a < num_base_verts; a++) { // loop through all inside edge pixels + dy = t - base_verts[a].x; // compute delta in Y from gradient pixel to inside edge pixel + dx = fsz - base_verts[a].y; // compute delta in X from gradient pixel to inside edge pixel + ud = dx * dx + dy * dy; // compute sum of squares + if (ud < dmin) { // if our new sum of squares is less than the current minimum we've found + dmin = ud; // set a new minimum equal to the new lower value + } + } + idist = (float)(dmin); // cast inner min to a float + rsf = idist * 0.5f; // + rsl = *(unsigned int *)&idist; // + rsl = 0x5f3759df - (rsl >> 1); // see notes above + idist = *(float *)&rsl; // + idist = idist * (rsopf - (rsf * idist * idist)); // + /* + * Note once again that since we are using reciprocals of distance values our + * proportion is already the correct intensity, and does not need to be + * subracted from 1.0 like it would have if we used real distances. + */ + + /* set intensity, do the += so overlapping gradients are additive */ + *cpxl = (idist / (idist + odist)); +/* + * End modified code from double edge mask node + */ + } + } + } + } + + /* + * Loop through all edges of polygon that could be hit by this scan line, + * and figure out their x-intersections with the next scan line. + * + * Either A.) we wont have any more edges to test, or B.) we just add on the + * slope delta computed in preprocessing step. Since this draws non-antialiased + * polygons, we dont have fractional positions, so we only move in x-direction + * when needed to get all the way to the next pixel over... + */ + for (edgec = &ctx->possible_edges; (e_curr = *edgec); ) { + if (!(--(e_curr->num))) { + *edgec = e_curr->e_next; + } + else { + e_curr->x += e_curr->xshift; + if ((e_curr->drift += e_curr->drift_inc) > 0) { + e_curr->x += e_curr->xdir; + e_curr->drift -= e_curr->drift_dec; + } + edgec = &e_curr->e_next; + } + } + /* + * It's possible that some edges may have crossed during the last step, so we'll be sure + * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges + * sorted by x-intersection coordinate. We'll always scan through at least once to see if + * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial + * pass, then we know we need to sort by x, so then cycle through edges again and perform + * the sort.- + */ + if (ctx->possible_edges) { + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ + if (e_curr->x > e_curr->e_next->x) { + *edgec = e_curr->e_next; + /* exchange the pointers */ + e_temp = e_curr->e_next->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + /* set flag that we had at least one switch */ + swixd = 1; + } + } + /* if we did have a switch, look for more (there will more if there was one) */ + for (;; ) { + /* reset exchange flag so it's only set if we encounter another one */ + swixd = 0; + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + /* again, if current edge hits scan line at higher X than next edge, + * exchange the edges and set flag */ + if (e_curr->x > e_curr->e_next->x) { + *edgec = e_curr->e_next; + /* exchange the pointers */ + e_temp = e_curr->e_next->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + /* flip the exchanged flag */ + swixd = 1; + } + } + /* if we had no exchanges, we're done reshuffling the pointers */ + if (!swixd) { + break; + } + } + } + } + + free(edgbuf); + return 1; +} + +int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*feather_verts)[2], int num_feather_verts, + float *buf, int buf_x, int buf_y) +{ + int i; /* i: Loop counter. */ + struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ + struct poly_vert *fe; /* fe: Pointer to a list of integer buffer-space feather vertex coords. */ + struct r_fill_context ctx = {0}; + + /* + * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert + * data structure multiplied by the number of verts. + * + * In the event of a failure to allocate the memory, return 0, so this error can + * be distinguished as a memory allocation error. + */ + if ((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_base_verts))) == NULL) { + return(0); + } + + if ((fe = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_feather_verts))) == NULL) { + return(0); + } + + /* + * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are + * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates + * in the buffer-space coordinates passed in inside buf_x and buf_y. + * + * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel + * drawn will be 1.0f in value, there is no anti-aliasing. + */ + for (i = 0; i < num_base_verts; i++) { /* Loop over all verts. */ + ply[i].x = (base_verts[i][0] * buf_x) + 0.5f; /* Range expand normalized X to integer buffer-space X. */ + ply[i].y = (base_verts[i][1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */ + } + for (i = 0; i < num_feather_verts; i++) { /* Loop over all verts. */ + fe[i].x = (feather_verts[i][0] * buf_x) + 0.5f; /* Range expand normalized X to integer buffer-space X. */ + fe[i].y = (feather_verts[i][1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */ + } + + ctx.rb.buf = buf; /* Set the output buffer pointer. */ + ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ + ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ + + /* Call our rasterizer, passing in the integer coords for each vert. */ + i = rast_scan_feather(&ctx, ply, num_base_verts, fe, num_feather_verts); + free(ply); /* Free the memory allocated for the integer coordinate table. */ + free(fe); + return i; /* Return the value returned by the rasterizer. */ +} diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h index 98aaf0f6885..3292d4f8163 100644 --- a/intern/raskter/raskter.h +++ b/intern/raskter/raskter.h @@ -48,7 +48,12 @@ struct scan_line_batch { extern "C" { #endif -int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y); +int PLX_raskterize(float (*base_verts)[2], int num_base_verts, + float *buf, int buf_x, int buf_y); + +int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, + float (*feather_verts)[2], int num_feather_verts, + float *buf, int buf_x, int buf_y); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 3421f5ad9e5..02d73d1463e 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1731,30 +1731,47 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) float *diff_points; int tot_diff_point; + float *diff_feather_points; + int tot_diff_feather_points; + diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); + diff_feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_diff_feather_points); /* TODO, make this optional! */ if (width != height) { float *fp; + float *ffp; int i; float asp; if (width < height) { fp = &diff_points[0]; + ffp = &diff_feather_points[0]; asp = (float)width / (float)height; } else { fp = &diff_points[1]; + ffp = &diff_feather_points[1]; asp = (float)height / (float)width; } for (i = 0; i < tot_diff_point; i++, fp += 2) { (*fp) = (((*fp) - 0.5f) / asp) + 0.5f; } + for (i = 0; i < tot_diff_feather_points; i++, ffp += 2) { + (*ffp) = (((*ffp) - 0.5f) / asp) + 0.5f; + } } if (tot_diff_point) { - PLX_raskterize(diff_points, tot_diff_point, buffer, width, height); + PLX_raskterize((float (*)[2])diff_points, tot_diff_point, buffer, width, height); + + if (tot_diff_feather_points) { + PLX_raskterize_feather((float (*)[2])diff_points, tot_diff_point, + (float (*)[2])diff_feather_points, tot_diff_feather_points, + buffer, width, height); + MEM_freeN(diff_feather_points); + } MEM_freeN(diff_points); } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 8df6e4c3748..c51601202ff 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1323,7 +1323,7 @@ static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTra fp[1] = stroke_points[i].y * height * aspy / ibuf->x - marker->search_min[1]; } - PLX_raskterize(mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y); + PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y); MEM_freeN(mask_points); } From 1794b9b00fbc7c505eba45600bc3e75c78be79aa Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 31 May 2012 09:01:15 +0000 Subject: [PATCH 128/183] Fixed memory leak caused by not freeing uw array for points in deformed spline --- source/blender/blenkernel/intern/mask.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 02d73d1463e..4884a1d013f 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1155,18 +1155,24 @@ void BKE_mask_update_deform(Mask *mask) void BKE_mask_spline_ensure_deform(MaskSpline *spline) { + int allocated_points = (MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform)); // printf("SPLINE ALLOC %p %d\n", spline->points_deform, (int)(MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform))); - if ((spline->points_deform == NULL) || - (MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform)) != spline->tot_point) - { + if (spline->points_deform == NULL || allocated_points != spline->tot_point) { printf("alloc new spline\n"); if (spline->points_deform) { + int i; + + for (i = 0; i < allocated_points; i++) { + MaskSplinePoint *point = &spline->points_deform[i]; + BKE_mask_point_free(point); + } + MEM_freeN(spline->points_deform); } - spline->points_deform = MEM_mallocN(sizeof(*spline->points_deform) * spline->tot_point, __func__); + spline->points_deform = MEM_callocN(sizeof(*spline->points_deform) * spline->tot_point, __func__); } else { // printf("alloc spline done\n"); @@ -1230,6 +1236,8 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) MaskSplinePoint *point_deform = &spline->points_deform[i]; float delta[2]; + BKE_mask_point_free(point_deform); + *point_deform = *point; point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; From 038f41c087223b2ba22e739fd00355c508defb6e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 09:35:50 +0000 Subject: [PATCH 129/183] minor refactor - use float (*)[2] for 2D point arratys. --- source/blender/blenkernel/BKE_mask.h | 6 +- source/blender/blenkernel/intern/mask.c | 74 +++++++++++++------------ source/blender/editors/mask/mask_draw.c | 16 ++++-- source/blender/editors/mask/mask_ops.c | 8 +-- 4 files changed, 55 insertions(+), 49 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index e21a2aa54e8..4032bf3002c 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -57,9 +57,9 @@ void BKE_mask_object_unique_name(struct Mask *mask, struct MaskObject *maskobj); /* splines */ struct MaskSpline *BKE_mask_spline_add(struct MaskObject *maskobj); int BKE_mask_spline_resolution(struct MaskSpline *spline); -float *BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point); -float *BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point); -float *BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point); +float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point))[2]; +float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point))[2]; +float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2]; /* point */ int BKE_mask_point_has_handle(struct MaskSplinePoint *point); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 4884a1d013f..0cbba350c89 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -216,12 +216,12 @@ int BKE_mask_spline_feather_resolution(MaskSpline *spline) return resol; } -float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) +float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); MaskSplinePoint *point, *prev; - float *diff_points, *fp; + float (*diff_points)[2], (*fp)[2]; int a, len, resol = BKE_mask_spline_resolution(spline); if (spline->tot_point <= 1) { @@ -240,7 +240,7 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) /* len+1 because of 'forward_diff_bezier' function */ *tot_diff_point = len; - diff_points = fp = MEM_callocN((len + 1) * 2 * sizeof(float), "mask spline vets"); + diff_points = fp = MEM_callocN((len + 1) * sizeof(*diff_points), "mask spline vets"); a = spline->tot_point - 1; if (spline->flag & MASK_SPLINE_CYCLIC) @@ -263,13 +263,13 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) for (j = 0; j < 2; j++) { BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], prevbezt->vec[2][j], bezt->vec[0][j], bezt->vec[1][j], - fp + j, resol, 2 * sizeof(float)); + &(*fp)[j], resol, 2 * sizeof(float)); } - fp += 2 * resol; + fp += resol; if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { - copy_v2_v2(fp, bezt->vec[1]); + copy_v2_v2(*fp, bezt->vec[1]); } prev = point; @@ -279,29 +279,30 @@ float *BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point) return diff_points; } -float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point) +float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - float *feather, *fp; + float (*feather)[2], (*fp)[2]; int i, j, tot, resol = BKE_mask_spline_feather_resolution(spline); tot = resol * spline->tot_point; - feather = fp = MEM_callocN(2 * tot * sizeof(float), "mask spline feather diff points"); + feather = fp = MEM_callocN(tot * sizeof(*feather), "mask spline feather diff points"); for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &points_array[i]; - for (j = 0; j < resol; j++, fp += 2) { + for (j = 0; j < resol; j++, fp++) { float u = (float) j / resol, weight; float co[2], n[2]; + /* TODO - these calls all calculate similar things + * could be unified for some speed */ BKE_mask_point_segment_co(spline, point, u, co); BKE_mask_point_normal(spline, point, u, n); weight = BKE_mask_point_weight(spline, point, u); - fp[0] = co[0] + n[0] * weight; - fp[1] = co[1] + n[1] * weight; + madd_v2_v2v2fl(*fp, co, n, weight); } } @@ -310,12 +311,12 @@ float *BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *to return feather; } -float *BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point) +float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, tot = 0; - float *feather, *fp; + float (*feather)[2], (*fp)[2]; /* count */ for (i = 0; i < spline->tot_point; i++) { @@ -325,7 +326,7 @@ float *BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point } /* create data */ - feather = fp = MEM_callocN(2 * tot * sizeof(float), "mask spline feather points"); + feather = fp = MEM_callocN(tot * sizeof(*feather), "mask spline feather points"); for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &points_array[i]; @@ -336,9 +337,8 @@ float *BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point BKE_mask_point_normal(spline, point, 0.0f, n); weight = BKE_mask_point_weight(spline, point, 0.0f); - fp[0] = bezt->vec[1][0] + n[0] * weight; - fp[1] = bezt->vec[1][1] + n[1] * weight; - fp += 2; + madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight); + fp++; for (j = 0; j < point->tot_uw; j++) { float u = point->uw[j].u; @@ -348,10 +348,8 @@ float *BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point BKE_mask_point_normal(spline, point, u, n); weight = BKE_mask_point_weight(spline, point, u); - fp[0] = co[0] + n[0] * weight; - fp[1] = co[1] + n[1] * weight; - - fp += 2; + madd_v2_v2v2fl(*fp, co, n, weight); + fp++; } } @@ -562,19 +560,23 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); - BezTriple *bezt = &point->bezt, *next; + BezTriple *bezt = &point->bezt, *bezt_next; float cur_u, cur_w, next_u, next_w, fac; int i; if (point == &points_array[spline->tot_point - 1]) { - if (spline->flag & MASK_SPLINE_CYCLIC) - next = &(points_array[0].bezt); - else - next = NULL; + if (spline->flag & MASK_SPLINE_CYCLIC) { + bezt_next = &(points_array[0].bezt); + } + else { + bezt_next = NULL; + } + } + else { + bezt_next = &((point + 1))->bezt; } - else next = &((point + 1))->bezt; - if (!next) + if (!bezt_next) return bezt->weight; for (i = 0; i < point->tot_uw + 1; i++) { @@ -590,7 +592,7 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) if (i == point->tot_uw) { next_u = 1.0f; - next_w = next->weight; + next_w = bezt_next->weight; } else { next_u = point->uw[i].u; @@ -1736,10 +1738,10 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) MaskSpline *spline; for (spline = maskobj->splines.first; spline; spline = spline->next) { - float *diff_points; + float (*diff_points)[2]; int tot_diff_point; - float *diff_feather_points; + float (*diff_feather_points)[2]; int tot_diff_feather_points; diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); @@ -1753,13 +1755,13 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) float asp; if (width < height) { - fp = &diff_points[0]; - ffp = &diff_feather_points[0]; + fp = &diff_points[0][0]; + ffp = &diff_feather_points[0][0]; asp = (float)width / (float)height; } else { - fp = &diff_points[1]; - ffp = &diff_feather_points[1]; + fp = &diff_points[0][1]; + ffp = &diff_feather_points[0][1]; asp = (float)height / (float)width; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 69c57018ab2..83d6c04c46d 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -126,7 +126,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, hsize, tot_feather_point; - float *feather_points, *fp; + float (*feather_points)[2], (*fp)[2]; if (!spline->tot_point) return; @@ -167,10 +167,10 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) } glBegin(GL_POINTS); - glVertex2fv(fp); + glVertex2fv(*fp); glEnd(); - fp += 2; + fp++; } } MEM_freeN(feather_points); @@ -236,7 +236,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) /* #define USE_XOR */ -static void mask_draw_curve_type(MaskSpline *spline, float *points, int tot_point, +static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot_point, const short is_feather, const short is_smooth, const unsigned char rgb_spline[4], const char draw_type) { @@ -329,8 +329,12 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, const short is_spline_sel = (spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0; const short is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH); - float *diff_points, *feather_points; - int tot_diff_point, tot_feather_point; + + int tot_diff_point; + float (*diff_points)[2]; + + int tot_feather_point; + float (*feather_points)[2]; diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index e06342090c2..53f87b92707 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -243,7 +243,7 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in //MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, tot_feather_point; - float *feather_points, *fp; + float (*feather_points)[2], (*fp)[2]; if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; @@ -258,8 +258,8 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in for (j = 0; j < cur_point->tot_uw + 1; j++) { float cur_len, vec[2]; - vec[0] = fp[0] * scalex; - vec[1] = fp[1] * scaley; + vec[0] = (*fp)[0] * scalex; + vec[1] = (*fp)[1] * scaley; cur_len = len_v2v2(vec, co); @@ -275,7 +275,7 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in len = cur_len; } - fp += 2; + fp++; } } From 332366643b58ebc2f2b14e361850669144e91990 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 09:46:17 +0000 Subject: [PATCH 130/183] use malloc for point arrays since they are filled in immediately. --- source/blender/blenkernel/BKE_mask.h | 1 + source/blender/blenkernel/intern/mask.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 4032bf3002c..7324f366e8d 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -57,6 +57,7 @@ void BKE_mask_object_unique_name(struct Mask *mask, struct MaskObject *maskobj); /* splines */ struct MaskSpline *BKE_mask_spline_add(struct MaskObject *maskobj); int BKE_mask_spline_resolution(struct MaskSpline *spline); + float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point))[2]; float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point))[2]; float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2]; diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 0cbba350c89..34396544b77 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -240,7 +240,7 @@ float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[ /* len+1 because of 'forward_diff_bezier' function */ *tot_diff_point = len; - diff_points = fp = MEM_callocN((len + 1) * sizeof(*diff_points), "mask spline vets"); + diff_points = fp = MEM_mallocN((len + 1) * sizeof(*diff_points), "mask spline vets"); a = spline->tot_point - 1; if (spline->flag & MASK_SPLINE_CYCLIC) @@ -287,7 +287,7 @@ float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *t int i, j, tot, resol = BKE_mask_spline_feather_resolution(spline); tot = resol * spline->tot_point; - feather = fp = MEM_callocN(tot * sizeof(*feather), "mask spline feather diff points"); + feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather diff points"); for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &points_array[i]; @@ -326,7 +326,7 @@ float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_poin } /* create data */ - feather = fp = MEM_callocN(tot * sizeof(*feather), "mask spline feather points"); + feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points"); for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &points_array[i]; From 998c34a7fa1551d65591d0855b3df3cd63769979 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 09:50:50 +0000 Subject: [PATCH 131/183] minor cleanup --- intern/raskter/raskter.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index c0da97ddbd5..fd274c5f5f5 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -388,7 +388,8 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ return 1; } -int PLX_raskterize(float (*base_verts)[2], int num_base_verts, float *buf, int buf_x, int buf_y) +int PLX_raskterize(float (*base_verts)[2], int num_base_verts, + float *buf, int buf_x, int buf_y) { int i; /* i: Loop counter. */ struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ @@ -718,13 +719,17 @@ int rast_scan_feather(struct r_fill_context *ctx, } int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*feather_verts)[2], int num_feather_verts, - float *buf, int buf_x, int buf_y) + float *buf, int buf_x, int buf_y) { int i; /* i: Loop counter. */ struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ struct poly_vert *fe; /* fe: Pointer to a list of integer buffer-space feather vertex coords. */ struct r_fill_context ctx = {0}; + /* for faster multiply */ + const float buf_x_f = (float)buf_x; + const float buf_y_f = (float)buf_y; + /* * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert * data structure multiplied by the number of verts. @@ -749,12 +754,12 @@ int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*f * drawn will be 1.0f in value, there is no anti-aliasing. */ for (i = 0; i < num_base_verts; i++) { /* Loop over all verts. */ - ply[i].x = (base_verts[i][0] * buf_x) + 0.5f; /* Range expand normalized X to integer buffer-space X. */ - ply[i].y = (base_verts[i][1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */ + ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ + ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */ } for (i = 0; i < num_feather_verts; i++) { /* Loop over all verts. */ - fe[i].x = (feather_verts[i][0] * buf_x) + 0.5f; /* Range expand normalized X to integer buffer-space X. */ - fe[i].y = (feather_verts[i][1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */ + fe[i].x = (int)((feather_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ + fe[i].y = (int)((feather_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */ } ctx.rb.buf = buf; /* Set the output buffer pointer. */ From efe289f3121f1eb9a7d85520cf5bfaeed88bcf50 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 31 May 2012 10:01:21 +0000 Subject: [PATCH 132/183] Fix adding feather points when there's deformed spline for mask Deformed spline should be re-evaluated after adding new feather points Used both BKE_mask_update_display and DAG_id_tag_update because of: - If adding feather point is happening from macro which adds point and slides it, deformed spline should be updated immediatelly so sliding operator will use updated feather, - If adding happens outside of such macro, update DAG is necessary to make needed updates in other areas (such as compositor, i.e.) --- source/blender/editors/mask/mask_ops.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 53f87b92707..2eaae673364 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1317,12 +1317,17 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &maskobj, &spline, &point, &u, NULL)) { + Scene *scene = CTX_data_scene(C); float w = BKE_mask_point_weight(spline, point, u); BKE_mask_point_add_uw(point, u, w); + BKE_mask_update_display(mask, scene->r.cfra); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + DAG_id_tag_update(&mask->id, 0); + return OPERATOR_FINISHED; } From 744360479060be75df955bef48987324eb8eec58 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 12:12:28 +0000 Subject: [PATCH 133/183] mask object blending and alpha options --- release/scripts/startup/bl_ui/space_clip.py | 7 ++ source/blender/blenkernel/intern/mask.c | 102 +++++++++++++++++- .../editors/interface/interface_templates.c | 1 + source/blender/makesdna/DNA_mask_types.h | 18 +++- source/blender/makesrna/intern/rna_mask.c | 36 ++++++- 5 files changed, 156 insertions(+), 8 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 6815aef56d6..a5b1996ae0d 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -591,6 +591,13 @@ class CLIP_PT_mask_objects(Panel): active = mask.objects.active if active: layout.prop(active, "name") + + # blending + row = layout.row(align=True) + row.prop(active, "alpha") + row.prop(active, "invert", text="", icon='IMAGE_ALPHA') + + layout.prop(active, "blend") class CLIP_PT_active_mask_spline(Panel): diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 34396544b77..42a083e56d7 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1729,13 +1729,57 @@ void BKE_mask_object_shape_changed_remove(MaskObject *maskobj, int index, int co } } +/* local functions */ +static void invert_vn_vn(float *array, const int size) +{ + float *arr = array + (size - 1); + int i = size; + while (i--) { + *(arr) = 1.0f - *(arr); + arr--; + } +} + +static void m_invert_vn_vn(float *array, const float f, const int size) +{ + float *arr = array + (size - 1); + int i = size; + while (i--) { + *(arr) = 1.0f - (*(arr) * f); + arr--; + } +} + +static void clamp_vn_vn(float *array, const int size) +{ + float *arr = array + (size - 1); + + int i = size; + while (i--) { + if (*arr < 0.0f) *arr = 0.0f; + else if (*arr > 1.0f) *arr = 1.0f; + arr--; + } +} + /* rasterization */ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) { MaskObject *maskobj; + /* temp blending buffer */ + const int buffer_size = width * height; + float *buffer_tmp = MEM_mallocN(sizeof(float) * buffer_size, __func__); + for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; + float alpha; + + if (maskobj->restrictflag & MASK_RESTRICT_RENDER) { + continue; + } + + memset(buffer_tmp, 0, sizeof(float) * buffer_size); for (spline = maskobj->splines.first; spline; spline = spline->next) { float (*diff_points)[2]; @@ -1774,17 +1818,67 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) } if (tot_diff_point) { - PLX_raskterize((float (*)[2])diff_points, tot_diff_point, buffer, width, height); + PLX_raskterize((float (*)[2])diff_points, tot_diff_point, + buffer_tmp, width, height); if (tot_diff_feather_points) { PLX_raskterize_feather((float (*)[2])diff_points, tot_diff_point, (float (*)[2])diff_feather_points, tot_diff_feather_points, - buffer, width, height); - MEM_freeN(diff_feather_points); + buffer_tmp, width, height); } - MEM_freeN(diff_points); + if (tot_diff_point) { + MEM_freeN(diff_points); + } + if (tot_diff_feather_points) { + MEM_freeN(diff_feather_points); + } } } + + /* blend with original */ + if (maskobj->blend_flag & MASK_BLENDFLAG_INVERT) { + /* apply alpha multiply before inverting */ + if (maskobj->alpha != 1.0f) { + m_invert_vn_vn(buffer_tmp, maskobj->alpha, buffer_size); + } + else { + invert_vn_vn(buffer_tmp, buffer_size); + } + + alpha = 1.0f; + } + else { + alpha = maskobj->alpha; + } + + switch (maskobj->blend) { + case MASK_BLEND_SUBTRACT: + { + if (alpha == 1.0f) { + sub_vn_vn(buffer, buffer_tmp, buffer_size); + } + else { + msub_vn_vn(buffer, buffer_tmp, alpha, buffer_size); + } + break; + } + case MASK_BLEND_ADD: + default: + { + if (alpha == 1.0f) { + add_vn_vn(buffer, buffer_tmp, buffer_size); + } + else { + madd_vn_vn(buffer, buffer_tmp, alpha, buffer_size); + } + break; + } + } + + /* clamp at the end */ + clamp_vn_vn(buffer, buffer_size); } + + MEM_freeN(buffer_tmp); } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 1acfefe8a4c..d23cd88cf05 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2251,6 +2251,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe // uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE); // enable when used uiItemR(row, itemptr, "hide", 0, "", 0); uiItemR(row, itemptr, "hide_select", 0, "", 0); + uiItemR(row, itemptr, "hide_render", 0, "", 0); uiBlockSetEmboss(block, UI_EMBOSS); } diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index d427e1561cb..d677239e300 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -108,10 +108,14 @@ typedef struct MaskObject { struct MaskSpline *act_spline; /* active spline */ struct MaskSplinePoint *act_point; /* active point */ + /* blending options */ float alpha; + char blend; + char blend_flag; + //char flag; /* not used yet */ char restrictflag; /* matching 'Object' flag of the same name - eventually use in the outliner */ - char pad[3]; + char pad[1]; } MaskObject; /* MaskParent->flag */ @@ -144,4 +148,16 @@ enum { MASK_DT_WHITE }; +/* maskobj->blend */ +enum { + MASK_BLEND_ADD = 0, + MASK_BLEND_SUBTRACT = 1 +}; + +/* maskobj->blend_flag */ +enum { + MASK_BLENDFLAG_INVERT = (1 << 0) +}; + + #endif // __DNA_MASK_TYPES_H__ diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 393ca5f3244..c072676b665 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -126,6 +126,11 @@ static void rna_Mask_object_active_index_range(PointerRNA *ptr, int *min, int *m *softmax = *max; } +static char *rna_MaskObject_path(PointerRNA *ptr) +{ + return BLI_sprintfN("objects[\"%s\"]", ((MaskObject *)ptr->data)->name); +} + static PointerRNA rna_Mask_object_active_get(PointerRNA *ptr) { Mask *mask = (Mask *)ptr->id.data; @@ -483,7 +488,8 @@ static void rna_def_maskSpline(BlenderRNA *brna) static EnumPropertyItem spline_interpolation_items[] = { {MASK_SPLINE_INTERP_LINEAR, "LINEAR", 0, "Linear", ""}, {MASK_SPLINE_INTERP_EASE, "EASE", 0, "Ease", ""}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL} + }; StructRNA *srna; PropertyRNA *prop; @@ -510,6 +516,12 @@ static void rna_def_maskSpline(BlenderRNA *brna) static void rna_def_mask_object(BlenderRNA *brna) { + static EnumPropertyItem maskobj_blend_mode_items[] = { + {MASK_BLEND_ADD, "ADD", 0, "Add", ""}, + {MASK_BLEND_SUBTRACT, "SUBTRACT", 0, "Subtract", ""}, + {0, NULL, 0, NULL, NULL} + }; + StructRNA *srna; PropertyRNA *prop; @@ -518,6 +530,7 @@ static void rna_def_mask_object(BlenderRNA *brna) srna = RNA_def_struct(brna, "MaskObject", NULL); RNA_def_struct_ui_text(srna, "Mask Object", "Single object used for masking pixels"); + RNA_def_struct_path_func(srna, "rna_MaskObject_path"); /* name */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); @@ -551,14 +564,28 @@ static void rna_def_mask_object(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_RENDER); RNA_def_property_ui_text(prop, "Restrict Render", "Restrict renderability"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1); - RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); + RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); /* render settings */ prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "alpha"); RNA_def_property_range(prop, 0.0, 1.0f); RNA_def_property_ui_text(prop, "Opacity", "Render Opacity"); - RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); + RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); + + /* weight interpolation */ + prop = RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "blend"); + RNA_def_property_enum_items(prop, maskobj_blend_mode_items); + RNA_def_property_ui_text(prop, "Blend", "Method of blending mask objects"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); + + prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MASK_BLENDFLAG_INVERT); + RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport"); + RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); + } static void rna_def_maskobjects(BlenderRNA *brna, PropertyRNA *cprop) @@ -616,6 +643,9 @@ static void rna_def_mask(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_funcs(prop, "rna_Mask_object_active_index_get", "rna_Mask_object_active_index_set", "rna_Mask_object_active_index_range"); RNA_def_property_ui_text(prop, "Active Shape Index", "Index of active object in list of all mask's objects"); + + /* pointers */ + rna_def_animdata_common(srna); } void RNA_def_mask(BlenderRNA *brna) From 153259ff7441b496264db217983adffee36f963f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 12:24:06 +0000 Subject: [PATCH 134/183] support for mask keyframing --- source/blender/blenkernel/intern/anim_sys.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 1358c2e34a8..7fc80529753 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -90,6 +90,7 @@ short id_type_can_have_animdata(ID *id) case ID_SPK: case ID_SCE: case ID_MC: + case ID_MSK: { return 1; } @@ -802,10 +803,13 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u /* objects */ ANIMDATA_IDS_CB(mainptr->object.first); + + /* masks */ + ANIMDATA_IDS_CB(mainptr->mask.first); /* worlds */ ANIMDATA_IDS_CB(mainptr->world.first); - + /* scenes */ ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene); } @@ -886,6 +890,9 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha /* objects */ RENAMEFIX_ANIM_IDS(mainptr->object.first); + + /* masks */ + RENAMEFIX_ANIM_IDS(mainptr->mask.first); /* worlds */ RENAMEFIX_ANIM_IDS(mainptr->world.first); @@ -2350,6 +2357,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) * linked from other (not-visible) scenes will not need their data calculated. */ EVAL_ANIM_IDS(main->object.first, 0); + + /* masks */ + EVAL_ANIM_IDS(main->mask.first, ADT_RECALC_ANIM); /* worlds */ EVAL_ANIM_NODETREE_IDS(main->world.first, World, ADT_RECALC_ANIM); From 58a7c451c1d9eecb59de46995386272154cbf582 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 13:37:32 +0000 Subject: [PATCH 135/183] convert mask to linear color. --- source/blender/blenkernel/intern/mask.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 42a083e56d7..bfe8ae54e0c 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1750,7 +1750,7 @@ static void m_invert_vn_vn(float *array, const float f, const int size) } } -static void clamp_vn_vn(float *array, const int size) +static void linear_clamp_vn_vn(float *array, const int size) { float *arr = array + (size - 1); @@ -1758,6 +1758,7 @@ static void clamp_vn_vn(float *array, const int size) while (i--) { if (*arr < 0.0f) *arr = 0.0f; else if (*arr > 1.0f) *arr = 1.0f; + else *arr = srgb_to_linearrgb(*arr); arr--; } } @@ -1877,7 +1878,7 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) } /* clamp at the end */ - clamp_vn_vn(buffer, buffer_size); + linear_clamp_vn_vn(buffer, buffer_size); } MEM_freeN(buffer_tmp); From 198a914db12a02e85114513f7a5f2ef3124b4443 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 13:43:21 +0000 Subject: [PATCH 136/183] save calling srgb_to_linearrgb() for 0 or 1 when converting mask color. --- source/blender/blenkernel/intern/mask.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index bfe8ae54e0c..7070edc0054 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1756,9 +1756,9 @@ static void linear_clamp_vn_vn(float *array, const int size) int i = size; while (i--) { - if (*arr < 0.0f) *arr = 0.0f; - else if (*arr > 1.0f) *arr = 1.0f; - else *arr = srgb_to_linearrgb(*arr); + if (*arr <= 0.0f) *arr = 0.0f; + else if (*arr >= 1.0f) *arr = 1.0f; + else *arr = srgb_to_linearrgb(*arr); arr--; } } From 65c8a338429e3d2b07e77e5c65265d4fc17134b8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 14:03:25 +0000 Subject: [PATCH 137/183] fix for using wrong poll function in mask parenting --- source/blender/editors/mask/mask_relationships.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index c799ca1e071..bf57bce9957 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -97,7 +97,7 @@ void MASK_OT_parent_clear(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_parent_clear_exec; - ot->poll = ED_operator_object_active_editable; + ot->poll = ED_maskediting_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -176,7 +176,7 @@ void MASK_OT_parent_set(wmOperatorType *ot) //ot->invoke = mask_parent_set_invoke; ot->exec = mask_parent_set_exec; - ot->poll = ED_operator_object_active; + ot->poll = ED_maskediting_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; From 0451dedf6f1838aebe8dbc8205aa2b110fcefe89 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Thu, 31 May 2012 14:29:09 +0000 Subject: [PATCH 138/183] remove some redundant checks when freeing memory after rasterizing masks. --- source/blender/blenkernel/intern/mask.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 7070edc0054..363efd2dd54 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1826,14 +1826,10 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) PLX_raskterize_feather((float (*)[2])diff_points, tot_diff_point, (float (*)[2])diff_feather_points, tot_diff_feather_points, buffer_tmp, width, height); - } - - if (tot_diff_point) { - MEM_freeN(diff_points); - } - if (tot_diff_feather_points) { MEM_freeN(diff_feather_points); } + + MEM_freeN(diff_points); } } From f7fb32fb8a6270df6416c0894230308f854fa404 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Thu, 31 May 2012 14:36:22 +0000 Subject: [PATCH 139/183] Fix possible memory leak where spline differentiation fails but feather differentiation does not. --- source/blender/blenkernel/intern/mask.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 363efd2dd54..d1ed99bd0c6 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1790,7 +1790,9 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) int tot_diff_feather_points; diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); - diff_feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_diff_feather_points); + if(tot_diff_point){ + diff_feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_diff_feather_points); + } /* TODO, make this optional! */ if (width != height) { From 55621216ceee1bb962f687255d57fb802952a6d0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 15:37:44 +0000 Subject: [PATCH 140/183] fix for border/circle/lasso select not using the deformed locations when selecting. --- source/blender/editors/mask/mask_select.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 05dad9f380f..c204dbf0110 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -390,13 +390,16 @@ static int border_select_exec(bContext *C, wmOperator *op) } for (spline = maskobj->splines.first; spline; spline = spline->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point_deform = &points_array[i]; /* TODO: handles? */ /* TODO: uw? */ - if (BLI_in_rctf(&rectf, point->bezt.vec[1][0], point->bezt.vec[1][1])) { + if (BLI_in_rctf(&rectf, point_deform->bezt.vec[1][0], point_deform->bezt.vec[1][1])) { BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT); BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT); } @@ -462,8 +465,11 @@ static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short } for (spline = maskobj->splines.first; spline; spline = spline->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point_deform = &points_array[i]; /* TODO: handles? */ /* TODO: uw? */ @@ -472,7 +478,7 @@ static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short /* marker in screen coords */ ED_mask_point_pos__reverse(C, - point->bezt.vec[1][0], point->bezt.vec[1][1], + point_deform->bezt.vec[1][0], point_deform->bezt.vec[1][1], &screen_co[0], &screen_co[1]); if (BLI_in_rcti(&rect, screen_co[0], screen_co[1]) && @@ -539,15 +545,15 @@ void MASK_OT_select_lasso(wmOperatorType *ot) /********************** circle select operator *********************/ -static int mask_spline_point_inside_ellipse(MaskSplinePoint *point, float offset[2], float ellipse[2]) +static int mask_spline_point_inside_ellipse(BezTriple *bezt, float offset[2], float ellipse[2]) { /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ float x, y; - x = (point->bezt.vec[1][0] - offset[0]) * ellipse[0]; - y = (point->bezt.vec[1][1] - offset[1]) * ellipse[1]; + x = (bezt->vec[1][0] - offset[0]) * ellipse[0]; + y = (bezt->vec[1][1] - offset[1]) * ellipse[1]; - return x*x + y*y < 1.0f; + return x * x + y * y < 1.0f; } static int circle_select_exec(bContext *C, wmOperator *op) @@ -588,10 +594,13 @@ static int circle_select_exec(bContext *C, wmOperator *op) } for (spline = maskobj->splines.first; spline; spline = spline->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point_deform = &points_array[i]; - if (mask_spline_point_inside_ellipse(point, offset, ellipse)) { + if (mask_spline_point_inside_ellipse(&point_deform->bezt, offset, ellipse)) { BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT); BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT); From 3834134cf0585adc61ab988d522467e534225d2f Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Thu, 31 May 2012 16:59:25 +0000 Subject: [PATCH 141/183] Add dynamic mask curve differentiation for more accurate feather gradients. --- source/blender/blenkernel/BKE_mask.h | 6 ++-- source/blender/blenkernel/intern/mask.c | 41 +++++++++++++++++-------- source/blender/editors/mask/mask_draw.c | 4 +-- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 7324f366e8d..5663aa69e8b 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -56,10 +56,10 @@ void BKE_mask_object_unique_name(struct Mask *mask, struct MaskObject *maskobj); /* splines */ struct MaskSpline *BKE_mask_spline_add(struct MaskObject *maskobj); -int BKE_mask_spline_resolution(struct MaskSpline *spline); +int BKE_mask_spline_resolution(struct MaskSpline *spline, float max_seg_len); -float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point))[2]; -float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point))[2]; +float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point, int dynamic_res, float max_dseg_len))[2]; +float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point, int dynamic_res, float max_dseg_len))[2]; float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2]; /* point */ diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index d1ed99bd0c6..9e509c10989 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -149,9 +149,9 @@ MaskSpline *BKE_mask_spline_add(MaskObject *maskobj) return spline; } -int BKE_mask_spline_resolution(MaskSpline *spline) +int BKE_mask_spline_resolution(MaskSpline *spline, float max_seg_len) { - const float max_segment = 0.01; + const float max_segment = max_seg_len; int i, resol = 1; for (i = 0; i < spline->tot_point; i++) { @@ -186,10 +186,10 @@ int BKE_mask_spline_resolution(MaskSpline *spline) return resol; } -int BKE_mask_spline_feather_resolution(MaskSpline *spline) +int BKE_mask_spline_feather_resolution(MaskSpline *spline, float max_seg_len) { const float max_segment = 0.005; - int resol = BKE_mask_spline_resolution(spline); + int resol = BKE_mask_spline_resolution(spline, max_seg_len); float max_jump = 0.0f; int i; @@ -216,13 +216,18 @@ int BKE_mask_spline_feather_resolution(MaskSpline *spline) return resol; } -float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2] +float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point, int dynamic_res, float max_dseg_len))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); MaskSplinePoint *point, *prev; float (*diff_points)[2], (*fp)[2]; - int a, len, resol = BKE_mask_spline_resolution(spline); + int a, len, resol; + if(!dynamic_res){ + max_dseg_len = 0.01f; + } + resol = BKE_mask_spline_resolution(spline, max_dseg_len); + if (spline->tot_point <= 1) { /* nothing to differentiate */ @@ -279,12 +284,16 @@ float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[ return diff_points; } -float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2] +float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point, int dynamic_res, float max_dseg_len))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); float (*feather)[2], (*fp)[2]; - int i, j, tot, resol = BKE_mask_spline_feather_resolution(spline); + int i, j, tot, resol; + if(!dynamic_res){ + max_dseg_len = 0.005f; + } + resol = BKE_mask_spline_feather_resolution(spline, max_dseg_len); tot = resol * spline->tot_point; feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather diff points"); @@ -429,7 +438,7 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_feather_point) { float *feather, *fp; - int i, resol = BKE_mask_spline_feather_resolution(spline); + int i, resol = BKE_mask_spline_feather_resolution(spline, 0.005f); feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); @@ -456,7 +465,7 @@ float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, i BezTriple *bezt, *next; float *diff_points, *fp; - int j, resol = BKE_mask_spline_resolution(spline); + int j, resol = BKE_mask_spline_resolution(spline, 0.01f); bezt = &point->bezt; @@ -1771,6 +1780,14 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) /* temp blending buffer */ const int buffer_size = width * height; float *buffer_tmp = MEM_mallocN(sizeof(float) * buffer_size, __func__); + float max_dseg_len = 0.0f; + + if(width >= height){ + max_dseg_len = (float)(width); + }else{ + max_dseg_len = (float)(height); + } + max_dseg_len = 1.0f / max_dseg_len; for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { MaskSpline *spline; @@ -1789,9 +1806,9 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) float (*diff_feather_points)[2]; int tot_diff_feather_points; - diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); + diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point, 1, max_dseg_len); if(tot_diff_point){ - diff_feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_diff_feather_points); + diff_feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_diff_feather_points, 1, max_dseg_len); } /* TODO, make this optional! */ diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 83d6c04c46d..c282153acbf 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -336,7 +336,7 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, int tot_feather_point; float (*feather_points)[2]; - diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point); + diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point, 0, 0.0f); if (!diff_points) return; @@ -347,7 +347,7 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_feather_point); + feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_feather_point, 0, 0.0f); /* draw feather */ mask_spline_feather_color_get(maskobj, spline, is_spline_sel, rgb_tmp); From 192a28bb32e8888c4477f724bfab036a466458be Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2012 19:12:22 +0000 Subject: [PATCH 142/183] rename mask-objects to mask-layers. --- release/scripts/startup/bl_ui/space_clip.py | 20 +- source/blender/blenkernel/BKE_mask.h | 60 +-- source/blender/blenkernel/intern/mask.c | 404 +++++++++--------- source/blender/blenloader/intern/readfile.c | 28 +- source/blender/blenloader/intern/writefile.c | 16 +- .../editors/animation/keyframes_draw.c | 44 +- .../editors/include/ED_keyframes_draw.h | 4 +- source/blender/editors/include/ED_mask.h | 2 +- .../editors/interface/interface_templates.c | 2 +- source/blender/editors/mask/mask_draw.c | 54 +-- source/blender/editors/mask/mask_editor.c | 6 +- source/blender/editors/mask/mask_intern.h | 12 +- source/blender/editors/mask/mask_ops.c | 286 ++++++------- .../blender/editors/mask/mask_relationships.c | 16 +- source/blender/editors/mask/mask_select.c | 90 ++-- source/blender/editors/mask/mask_shapekey.c | 38 +- source/blender/editors/screen/screen_ops.c | 4 +- source/blender/editors/space_clip/clip_draw.c | 14 +- .../editors/transform/transform_conversions.c | 20 +- source/blender/makesdna/DNA_mask_types.h | 28 +- source/blender/makesrna/RNA_access.h | 2 +- source/blender/makesrna/intern/rna_mask.c | 186 ++++---- 22 files changed, 668 insertions(+), 668 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index a5b1996ae0d..ab1bd817490 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -565,7 +565,7 @@ class CLIP_PT_tracking_camera(Panel): class CLIP_PT_mask_objects(Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' - bl_label = "Mask Objects" + bl_label = "Mask Layers" @classmethod def poll(cls, context): @@ -580,15 +580,15 @@ class CLIP_PT_mask_objects(Panel): mask = sc.mask row = layout.row() - row.template_list(mask, "objects", - mask, "active_object_index", rows=3) + row.template_list(mask, "layers", + mask, "active_layer_index", rows=3) sub = row.column(align=True) - sub.operator("mask.object_new", icon='ZOOMIN', text="") - sub.operator("mask.object_remove", icon='ZOOMOUT', text="") + sub.operator("mask.layer_new", icon='ZOOMIN', text="") + sub.operator("mask.layer_remove", icon='ZOOMOUT', text="") - active = mask.objects.active + active = mask.layers.active if active: layout.prop(active, "name") @@ -611,7 +611,7 @@ class CLIP_PT_active_mask_spline(Panel): mask = sc.mask if mask and sc.mode == 'MASKEDITING': - return mask.objects.active and mask.objects.active.splines.active + return mask.layers.active and mask.layers.active.splines.active return False @@ -620,7 +620,7 @@ class CLIP_PT_active_mask_spline(Panel): sc = context.space_data mask = sc.mask - spline = mask.objects.active.splines.active + spline = mask.layers.active.splines.active col = layout.column() col.prop(spline, "weight_interpolation") @@ -638,7 +638,7 @@ class CLIP_PT_active_mask_point(Panel): mask = sc.mask if mask and sc.mode == 'MASKEDITING': - return mask.objects.active and mask.objects.active.splines.active_point + return mask.layers.active and mask.layers.active.splines.active_point return False @@ -647,7 +647,7 @@ class CLIP_PT_active_mask_point(Panel): sc = context.space_data mask = sc.mask - point = mask.objects.active.splines.active_point + point = mask.layers.active.splines.active_point parent = point.parent col = layout.column() diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 5663aa69e8b..8fc979e941b 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -30,8 +30,8 @@ struct Main; struct Mask; struct MaskParent; -struct MaskObject; -struct MaskObjectShape; +struct MaskLayer; +struct MaskLayerShape; struct MaskSpline; struct MaskSplinePoint; struct MaskSplinePointUW; @@ -42,20 +42,20 @@ struct Scene; struct MaskSplinePoint *BKE_mask_spline_point_array(struct MaskSpline *spline); struct MaskSplinePoint *BKE_mask_spline_point_array_from_point(struct MaskSpline *spline, struct MaskSplinePoint *point_ref); -/* mask objects */ -struct MaskObject *BKE_mask_object_new(struct Mask *mask, const char *name); -struct MaskObject *BKE_mask_object_active(struct Mask *mask); -void BKE_mask_object_active_set(struct Mask *mask, struct MaskObject *maskobj); -void BKE_mask_object_remove(struct Mask *mask, struct MaskObject *maskobj); +/* mask layers */ +struct MaskLayer *BKE_mask_layer_new(struct Mask *mask, const char *name); +struct MaskLayer *BKE_mask_layer_active(struct Mask *mask); +void BKE_mask_layer_active_set(struct Mask *mask, struct MaskLayer *masklay); +void BKE_mask_layer_remove(struct Mask *mask, struct MaskLayer *masklay); -void BKE_mask_object_free(struct MaskObject *maskobj); +void BKE_mask_layer_free(struct MaskLayer *masklay); void BKE_mask_spline_free(struct MaskSpline *spline); void BKE_mask_point_free(struct MaskSplinePoint *point); -void BKE_mask_object_unique_name(struct Mask *mask, struct MaskObject *maskobj); +void BKE_mask_layer_unique_name(struct Mask *mask, struct MaskLayer *masklay); /* splines */ -struct MaskSpline *BKE_mask_spline_add(struct MaskObject *maskobj); +struct MaskSpline *BKE_mask_spline_add(struct MaskLayer *masklay); int BKE_mask_spline_resolution(struct MaskSpline *spline, float max_seg_len); float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point, int dynamic_res, float max_dseg_len))[2]; @@ -107,31 +107,31 @@ void BKE_mask_calc_handles(struct Mask *mask); void BKE_mask_spline_ensure_deform(struct MaskSpline *spline); /* animation */ -int BKE_mask_object_shape_totvert(struct MaskObject *maskobj); -void BKE_mask_object_shape_from_mask(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape); -void BKE_mask_object_shape_to_mask(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape); -void BKE_mask_object_shape_to_mask_interp(struct MaskObject *maskobj, - struct MaskObjectShape *maskobj_shape_a, - struct MaskObjectShape *maskobj_shape_b, +int BKE_mask_layer_shape_totvert(struct MaskLayer *masklay); +void BKE_mask_layer_shape_from_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); +void BKE_mask_layer_shape_to_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); +void BKE_mask_layer_shape_to_mask_interp(struct MaskLayer *masklay, + struct MaskLayerShape *masklay_shape_a, + struct MaskLayerShape *masklay_shape_b, const float fac); -struct MaskObjectShape *BKE_mask_object_shape_find_frame(struct MaskObject *maskobj, int frame); -int BKE_mask_object_shape_find_frame_range(struct MaskObject *maskobj, int frame, - struct MaskObjectShape **r_maskobj_shape_a, - struct MaskObjectShape **r_maskobj_shape_b); -struct MaskObjectShape *BKE_mask_object_shape_varify_frame(struct MaskObject *maskobj, int frame); -void BKE_mask_object_shape_unlink(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape); -void BKE_mask_object_shape_sort(struct MaskObject *maskobj); +struct MaskLayerShape *BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, int frame); +int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, int frame, + struct MaskLayerShape **r_masklay_shape_a, + struct MaskLayerShape **r_masklay_shape_b); +struct MaskLayerShape *BKE_mask_layer_shape_varify_frame(struct MaskLayer *masklay, int frame); +void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); +void BKE_mask_layer_shape_sort(struct MaskLayer *masklay); -int BKE_mask_object_shape_spline_from_index(struct MaskObject *maskobj, int index, - struct MaskSpline **r_maskobj_shape, int *r_index); -int BKE_mask_object_shape_spline_to_index(struct MaskObject *maskobj, struct MaskSpline *spline); +int BKE_mask_layer_shape_spline_from_index(struct MaskLayer *masklay, int index, + struct MaskSpline **r_masklay_shape, int *r_index); +int BKE_mask_layer_shape_spline_to_index(struct MaskLayer *masklay, struct MaskSpline *spline); -int BKE_mask_object_shape_spline_index(struct MaskObject *maskobj, int index, - struct MaskSpline **r_maskobj_shape, int *r_index); -void BKE_mask_object_shape_changed_add(struct MaskObject *maskobj, int index, +int BKE_mask_layer_shape_spline_index(struct MaskLayer *masklay, int index, + struct MaskSpline **r_masklay_shape, int *r_index); +void BKE_mask_layer_shape_changed_add(struct MaskLayer *masklay, int index, int do_init, int do_init_interpolate); -void BKE_mask_object_shape_changed_remove(struct MaskObject *maskobj, int index, int count); +void BKE_mask_layer_shape_changed_remove(struct MaskLayer *masklay, int index, int count); /* rasterization */ void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 9e509c10989..e6f328546f5 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -77,63 +77,63 @@ MaskSplinePoint *BKE_mask_spline_point_array_from_point(MaskSpline *spline, Mask return NULL; } -/* mask objects */ +/* mask layers */ -MaskObject *BKE_mask_object_new(Mask *mask, const char *name) +MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name) { - MaskObject *maskobj = MEM_callocN(sizeof(MaskObject), "new mask object"); + MaskLayer *masklay = MEM_callocN(sizeof(MaskLayer), __func__); if (name && name[0]) - BLI_strncpy(maskobj->name, name, sizeof(maskobj->name)); + BLI_strncpy(masklay->name, name, sizeof(masklay->name)); else - strcpy(maskobj->name, "MaskObject"); + strcpy(masklay->name, "MaskLayer"); - BLI_addtail(&mask->maskobjs, maskobj); + BLI_addtail(&mask->masklayers, masklay); - BKE_mask_object_unique_name(mask, maskobj); + BKE_mask_layer_unique_name(mask, masklay); - mask->tot_maskobj++; + mask->masklay_tot++; - maskobj->alpha = 1.0f; + masklay->alpha = 1.0f; - return maskobj; + return masklay; } /* note: may still be hidden, caller needs to check */ -MaskObject *BKE_mask_object_active(Mask *mask) +MaskLayer *BKE_mask_layer_active(Mask *mask) { - return BLI_findlink(&mask->maskobjs, mask->act_maskobj); + return BLI_findlink(&mask->masklayers, mask->masklay_act); } -void BKE_mask_object_active_set(Mask *mask, MaskObject *maskobj) +void BKE_mask_layer_active_set(Mask *mask, MaskLayer *masklay) { - mask->act_maskobj = BLI_findindex(&mask->maskobjs, maskobj); + mask->masklay_act = BLI_findindex(&mask->masklayers, masklay); } -void BKE_mask_object_remove(Mask *mask, MaskObject *maskobj) +void BKE_mask_layer_remove(Mask *mask, MaskLayer *masklay) { - BLI_remlink(&mask->maskobjs, maskobj); - BKE_mask_object_free(maskobj); + BLI_remlink(&mask->masklayers, masklay); + BKE_mask_layer_free(masklay); - mask->tot_maskobj--; + mask->masklay_tot--; - if (mask->act_maskobj >= mask->tot_maskobj) - mask->act_maskobj = mask->tot_maskobj - 1; + if (mask->masklay_act >= mask->masklay_tot) + mask->masklay_act = mask->masklay_tot - 1; } -void BKE_mask_object_unique_name(Mask *mask, MaskObject *maskobj) +void BKE_mask_layer_unique_name(Mask *mask, MaskLayer *masklay) { - BLI_uniquename(&mask->maskobjs, maskobj, "MaskObject", '.', offsetof(MaskObject, name), sizeof(maskobj->name)); + BLI_uniquename(&mask->masklayers, masklay, "MaskLayer", '.', offsetof(MaskLayer, name), sizeof(masklay->name)); } /* splines */ -MaskSpline *BKE_mask_spline_add(MaskObject *maskobj) +MaskSpline *BKE_mask_spline_add(MaskLayer *masklay) { MaskSpline *spline; spline = MEM_callocN(sizeof(MaskSpline), "new mask spline"); - BLI_addtail(&maskobj->splines, spline); + BLI_addtail(&masklay->splines, spline); /* spline shall have one point at least */ spline->points = MEM_callocN(sizeof(MaskSplinePoint), "new mask spline point"); @@ -747,54 +747,54 @@ void BKE_mask_spline_free(MaskSpline *spline) MEM_freeN(spline); } -void BKE_mask_object_shape_free(MaskObjectShape *maskobj_shape) +void BKE_mask_layer_shape_free(MaskLayerShape *masklay_shape) { - MEM_freeN(maskobj_shape->data); + MEM_freeN(masklay_shape->data); - MEM_freeN(maskobj_shape); + MEM_freeN(masklay_shape); } -void BKE_mask_object_free(MaskObject *maskobj) +void BKE_mask_layer_free(MaskLayer *masklay) { MaskSpline *spline; - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; /* free splines */ - spline = maskobj->splines.first; + spline = masklay->splines.first; while (spline) { MaskSpline *next_spline = spline->next; - BLI_remlink(&maskobj->splines, spline); + BLI_remlink(&masklay->splines, spline); BKE_mask_spline_free(spline); spline = next_spline; } /* free animation data */ - maskobj_shape = maskobj->splines_shapes.first; - while (maskobj_shape) { - MaskObjectShape *next_maskobj_shape = maskobj_shape->next; + masklay_shape = masklay->splines_shapes.first; + while (masklay_shape) { + MaskLayerShape *next_masklay_shape = masklay_shape->next; - BLI_remlink(&maskobj->splines_shapes, maskobj_shape); - BKE_mask_object_shape_free(maskobj_shape); + BLI_remlink(&masklay->splines_shapes, masklay_shape); + BKE_mask_layer_shape_free(masklay_shape); - maskobj_shape = next_maskobj_shape; + masklay_shape = next_masklay_shape; } - MEM_freeN(maskobj); + MEM_freeN(masklay); } void BKE_mask_free(Mask *mask) { - MaskObject *maskobj = mask->maskobjs.first; + MaskLayer *masklay = mask->masklayers.first; - while (maskobj) { - MaskObject *next_maskobj = maskobj->next; + while (masklay) { + MaskLayer *next_masklay = masklay->next; - BLI_remlink(&mask->maskobjs, maskobj); - BKE_mask_object_free(maskobj); + BLI_remlink(&mask->masklayers, masklay); + BKE_mask_layer_free(masklay); - maskobj = next_maskobj; + masklay = next_masklay; } } @@ -1107,12 +1107,12 @@ void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplineP void BKE_mask_calc_handles(Mask *mask) { - MaskObject *maskobj; + MaskLayer *masklay; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -1129,12 +1129,12 @@ void BKE_mask_calc_handles(Mask *mask) void BKE_mask_update_deform(Mask *mask) { - MaskObject *maskobj; + MaskLayer *masklay; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -1192,35 +1192,35 @@ void BKE_mask_spline_ensure_deform(MaskSpline *spline) void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) { - MaskObject *maskobj; + MaskLayer *masklay; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { /* animation if available */ if (do_newframe) { - MaskObjectShape *maskobj_shape_a; - MaskObjectShape *maskobj_shape_b; + MaskLayerShape *masklay_shape_a; + MaskLayerShape *masklay_shape_b; int found; - if ((found = BKE_mask_object_shape_find_frame_range(maskobj, (int)ctime, - &maskobj_shape_a, &maskobj_shape_b))) + if ((found = BKE_mask_layer_shape_find_frame_range(masklay, (int)ctime, + &masklay_shape_a, &masklay_shape_b))) { if (found == 1) { #if 0 - printf("%s: exact %d %d (%d)\n", __func__, (int)ctime, BLI_countlist(&maskobj->splines_shapes), - maskobj_shape_a->frame); + printf("%s: exact %d %d (%d)\n", __func__, (int)ctime, BLI_countlist(&masklay->splines_shapes), + masklay_shape_a->frame); #endif - BKE_mask_object_shape_to_mask(maskobj, maskobj_shape_a); + BKE_mask_layer_shape_to_mask(masklay, masklay_shape_a); } else if (found == 2) { - float w = maskobj_shape_b->frame - maskobj_shape_a->frame; + float w = masklay_shape_b->frame - masklay_shape_a->frame; #if 0 - printf("%s: tween %d %d (%d %d)\n", __func__, (int)ctime, BLI_countlist(&maskobj->splines_shapes), - maskobj_shape_a->frame, maskobj_shape_b->frame); + printf("%s: tween %d %d (%d %d)\n", __func__, (int)ctime, BLI_countlist(&masklay->splines_shapes), + masklay_shape_a->frame, masklay_shape_b->frame); #endif - BKE_mask_object_shape_to_mask_interp(maskobj, maskobj_shape_a, maskobj_shape_b, - (ctime - maskobj_shape_a->frame) / w); + BKE_mask_layer_shape_to_mask_interp(masklay, masklay_shape_a, masklay_shape_b, + (ctime - masklay_shape_a->frame) / w); } else { /* always fail, should never happen */ @@ -1234,11 +1234,11 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) BKE_mask_calc_handles(mask); - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; int i; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { BKE_mask_spline_ensure_deform(spline); @@ -1267,12 +1267,12 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) void BKE_mask_update_display(Mask *mask, float ctime) { #if 0 - MaskObject *maskobj; + MaskLayer *masklay; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { if (spline->points_deform) { int i = 0; @@ -1324,21 +1324,21 @@ void BKE_mask_parent_init(MaskParent *parent) /* *** own animation/shapekey implimentation *** - * BKE_mask_object_shape_XXX */ + * BKE_mask_layer_shape_XXX */ -int BKE_mask_object_shape_totvert(MaskObject *maskobj) +int BKE_mask_layer_shape_totvert(MaskLayer *masklay) { int tot = 0; MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { tot += spline->tot_point; } return tot; } -static void mask_object_shape_from_mask_point(BezTriple *bezt, float fp[MASK_OBJECT_SHAPE_ELEM_SIZE]) +static void mask_layer_shape_from_mask_point(BezTriple *bezt, float fp[MASK_OBJECT_SHAPE_ELEM_SIZE]) { copy_v2_v2(&fp[0], bezt->vec[0]); copy_v2_v2(&fp[2], bezt->vec[1]); @@ -1347,7 +1347,7 @@ static void mask_object_shape_from_mask_point(BezTriple *bezt, float fp[MASK_OBJ fp[7] = bezt->radius; } -static void mask_object_shape_to_mask_point(BezTriple *bezt, float fp[MASK_OBJECT_SHAPE_ELEM_SIZE]) +static void mask_layer_shape_to_mask_point(BezTriple *bezt, float fp[MASK_OBJECT_SHAPE_ELEM_SIZE]) { copy_v2_v2(bezt->vec[0], &fp[0]); copy_v2_v2(bezt->vec[1], &fp[2]); @@ -1357,47 +1357,47 @@ static void mask_object_shape_to_mask_point(BezTriple *bezt, float fp[MASK_OBJEC } /* these functions match. copy is swapped */ -void BKE_mask_object_shape_from_mask(MaskObject *maskobj, MaskObjectShape *maskobj_shape) +void BKE_mask_layer_shape_from_mask(MaskLayer *masklay, MaskLayerShape *masklay_shape) { - int tot = BKE_mask_object_shape_totvert(maskobj); + int tot = BKE_mask_layer_shape_totvert(masklay); - if (maskobj_shape->tot_vert == tot) { - float *fp = maskobj_shape->data; + if (masklay_shape->tot_vert == tot) { + float *fp = masklay_shape->data; MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { - mask_object_shape_from_mask_point(&spline->points[i].bezt, fp); + mask_layer_shape_from_mask_point(&spline->points[i].bezt, fp); fp += MASK_OBJECT_SHAPE_ELEM_SIZE; } } } else { printf("%s: vert mismatch %d != %d (frame %d)\n", - __func__, maskobj_shape->tot_vert, tot, maskobj_shape->frame); + __func__, masklay_shape->tot_vert, tot, masklay_shape->frame); } } -void BKE_mask_object_shape_to_mask(MaskObject *maskobj, MaskObjectShape *maskobj_shape) +void BKE_mask_layer_shape_to_mask(MaskLayer *masklay, MaskLayerShape *masklay_shape) { - int tot = BKE_mask_object_shape_totvert(maskobj); + int tot = BKE_mask_layer_shape_totvert(masklay); - if (maskobj_shape->tot_vert == tot) { - float *fp = maskobj_shape->data; + if (masklay_shape->tot_vert == tot) { + float *fp = masklay_shape->data; MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { - mask_object_shape_to_mask_point(&spline->points[i].bezt, fp); + mask_layer_shape_to_mask_point(&spline->points[i].bezt, fp); fp += MASK_OBJECT_SHAPE_ELEM_SIZE; } } } else { printf("%s: vert mismatch %d != %d (frame %d)\n", - __func__, maskobj_shape->tot_vert, tot, maskobj_shape->frame); + __func__, masklay_shape->tot_vert, tot, masklay_shape->frame); } } @@ -1409,23 +1409,23 @@ BLI_INLINE void interp_v2_v2v2_flfl(float target[2], const float a[2], const flo } /* linear interpolation only */ -void BKE_mask_object_shape_to_mask_interp(MaskObject *maskobj, - MaskObjectShape *maskobj_shape_a, - MaskObjectShape *maskobj_shape_b, +void BKE_mask_layer_shape_to_mask_interp(MaskLayer *masklay, + MaskLayerShape *masklay_shape_a, + MaskLayerShape *masklay_shape_b, const float fac) { - int tot = BKE_mask_object_shape_totvert(maskobj); - if (maskobj_shape_a->tot_vert == tot && maskobj_shape_b->tot_vert == tot) { - float *fp_a = maskobj_shape_a->data; - float *fp_b = maskobj_shape_b->data; + int tot = BKE_mask_layer_shape_totvert(masklay); + if (masklay_shape_a->tot_vert == tot && masklay_shape_b->tot_vert == tot) { + float *fp_a = masklay_shape_a->data; + float *fp_b = masklay_shape_b->data; const float ifac = 1.0f - fac; MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { BezTriple *bezt = &spline->points[i].bezt; - /* *** BKE_mask_object_shape_from_mask - swapped *** */ + /* *** BKE_mask_layer_shape_from_mask - swapped *** */ interp_v2_v2v2_flfl(bezt->vec[0], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2; interp_v2_v2v2_flfl(bezt->vec[1], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2; interp_v2_v2v2_flfl(bezt->vec[2], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2; @@ -1436,23 +1436,23 @@ void BKE_mask_object_shape_to_mask_interp(MaskObject *maskobj, } else { printf("%s: vert mismatch %d != %d != %d (frame %d - %d)\n", - __func__, maskobj_shape_a->tot_vert, maskobj_shape_b->tot_vert, tot, - maskobj_shape_a->frame, maskobj_shape_b->frame); + __func__, masklay_shape_a->tot_vert, masklay_shape_b->tot_vert, tot, + masklay_shape_a->frame, masklay_shape_b->frame); } } -MaskObjectShape *BKE_mask_object_shape_find_frame(MaskObject *maskobj, int frame) +MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, int frame) { - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; - for (maskobj_shape = maskobj->splines_shapes.first; - maskobj_shape; - maskobj_shape = maskobj_shape->next) + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) { - if (frame == maskobj_shape->frame) { - return maskobj_shape; + if (frame == masklay_shape->frame) { + return masklay_shape; } - else if (frame < maskobj_shape->frame) { + else if (frame < masklay_shape->frame) { break; } } @@ -1461,106 +1461,106 @@ MaskObjectShape *BKE_mask_object_shape_find_frame(MaskObject *maskobj, int frame } /* when returning 2 - the frame isnt found but before/after frames are */ -int BKE_mask_object_shape_find_frame_range(MaskObject *maskobj, int frame, - MaskObjectShape **r_maskobj_shape_a, - MaskObjectShape **r_maskobj_shape_b) +int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, int frame, + MaskLayerShape **r_masklay_shape_a, + MaskLayerShape **r_masklay_shape_b) { - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; - for (maskobj_shape = maskobj->splines_shapes.first; - maskobj_shape; - maskobj_shape = maskobj_shape->next) + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) { - if (frame == maskobj_shape->frame) { - *r_maskobj_shape_a = maskobj_shape; - *r_maskobj_shape_b = NULL; + if (frame == masklay_shape->frame) { + *r_masklay_shape_a = masklay_shape; + *r_masklay_shape_b = NULL; return 1; } - else if (frame < maskobj_shape->frame) { - if (maskobj_shape->prev) { - *r_maskobj_shape_a = maskobj_shape->prev; - *r_maskobj_shape_b = maskobj_shape; + else if (frame < masklay_shape->frame) { + if (masklay_shape->prev) { + *r_masklay_shape_a = masklay_shape->prev; + *r_masklay_shape_b = masklay_shape; return 2; } else { - *r_maskobj_shape_a = maskobj_shape; - *r_maskobj_shape_b = NULL; + *r_masklay_shape_a = masklay_shape; + *r_masklay_shape_b = NULL; return 1; } } } - *r_maskobj_shape_a = NULL; - *r_maskobj_shape_b = NULL; + *r_masklay_shape_a = NULL; + *r_masklay_shape_b = NULL; return 0; } -MaskObjectShape *BKE_mask_object_shape_varify_frame(MaskObject *maskobj, int frame) +MaskLayerShape *BKE_mask_layer_shape_varify_frame(MaskLayer *masklay, int frame) { - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; - maskobj_shape = BKE_mask_object_shape_find_frame(maskobj, frame); + masklay_shape = BKE_mask_layer_shape_find_frame(masklay, frame); - if (maskobj_shape == NULL) { - int tot_vert = BKE_mask_object_shape_totvert(maskobj); + if (masklay_shape == NULL) { + int tot_vert = BKE_mask_layer_shape_totvert(masklay); - maskobj_shape = MEM_mallocN(sizeof(MaskObjectShape), __func__); - maskobj_shape->frame = frame; - maskobj_shape->tot_vert = tot_vert; - maskobj_shape->data = MEM_mallocN(tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + masklay_shape = MEM_mallocN(sizeof(MaskLayerShape), __func__); + masklay_shape->frame = frame; + masklay_shape->tot_vert = tot_vert; + masklay_shape->data = MEM_mallocN(tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); - BLI_addtail(&maskobj->splines_shapes, maskobj_shape); + BLI_addtail(&masklay->splines_shapes, masklay_shape); - BKE_mask_object_shape_sort(maskobj); + BKE_mask_layer_shape_sort(masklay); } #if 0 { - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; int i = 0; - for (maskobj_shape = maskobj->splines_shapes.first; - maskobj_shape; - maskobj_shape = maskobj_shape->next) + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) { - printf("mask %d, %d\n", i++, maskobj_shape->frame); + printf("mask %d, %d\n", i++, masklay_shape->frame); } } #endif - return maskobj_shape; + return masklay_shape; } -void BKE_mask_object_shape_unlink(MaskObject *maskobj, MaskObjectShape *maskobj_shape) +void BKE_mask_layer_shape_unlink(MaskLayer *masklay, MaskLayerShape *masklay_shape) { - BLI_remlink(&maskobj->splines_shapes, maskobj_shape); + BLI_remlink(&masklay->splines_shapes, masklay_shape); - BKE_mask_object_shape_free(maskobj_shape); + BKE_mask_layer_shape_free(masklay_shape); } -static int mask_object_shape_sort_cb(void *maskobj_shape_a_ptr, void *maskobj_shape_b_ptr) +static int mask_layer_shape_sort_cb(void *masklay_shape_a_ptr, void *masklay_shape_b_ptr) { - MaskObjectShape *maskobj_shape_a = (MaskObjectShape *)maskobj_shape_a_ptr; - MaskObjectShape *maskobj_shape_b = (MaskObjectShape *)maskobj_shape_b_ptr; + MaskLayerShape *masklay_shape_a = (MaskLayerShape *)masklay_shape_a_ptr; + MaskLayerShape *masklay_shape_b = (MaskLayerShape *)masklay_shape_b_ptr; - if (maskobj_shape_a->frame < maskobj_shape_b->frame) return -1; - else if (maskobj_shape_a->frame > maskobj_shape_b->frame) return 1; + if (masklay_shape_a->frame < masklay_shape_b->frame) return -1; + else if (masklay_shape_a->frame > masklay_shape_b->frame) return 1; else return 0; } -void BKE_mask_object_shape_sort(MaskObject *maskobj) +void BKE_mask_layer_shape_sort(MaskLayer *masklay) { - BLI_sortlist(&maskobj->splines_shapes, mask_object_shape_sort_cb); + BLI_sortlist(&masklay->splines_shapes, mask_layer_shape_sort_cb); } -int BKE_mask_object_shape_spline_from_index(MaskObject *maskobj, int index, - MaskSpline **r_maskobj_shape, int *r_index) +int BKE_mask_layer_shape_spline_from_index(MaskLayer *masklay, int index, + MaskSpline **r_masklay_shape, int *r_index) { MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { if (index < spline->tot_point) { - *r_maskobj_shape = spline; + *r_masklay_shape = spline; *r_index = index; return TRUE; } @@ -1570,11 +1570,11 @@ int BKE_mask_object_shape_spline_from_index(MaskObject *maskobj, int index, return FALSE; } -int BKE_mask_object_shape_spline_to_index(MaskObject *maskobj, MaskSpline *spline) +int BKE_mask_layer_shape_spline_to_index(MaskLayer *masklay, MaskSpline *spline) { MaskSpline *spline_iter; int i_abs = 0; - for (spline_iter = maskobj->splines.first; + for (spline_iter = masklay->splines.first; spline_iter && spline_iter != spline; i_abs += spline_iter->tot_point, spline_iter = spline_iter->next) { @@ -1608,21 +1608,21 @@ static void interp_weights_uv_v2_apply(const float uv[2], float r_pt[2], const f } /* when a now points added - resize all shapekey array */ -void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, +void BKE_mask_layer_shape_changed_add(MaskLayer *masklay, int index, int do_init, int do_init_interpolate) { - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; - /* spline index from maskobj */ + /* spline index from masklay */ MaskSpline *spline; int spline_point_index; - if (BKE_mask_object_shape_spline_from_index(maskobj, index, + if (BKE_mask_layer_shape_spline_from_index(masklay, index, &spline, &spline_point_index)) { /* sanity check */ /* the point has already been removed in this array so subtract one when comparing with the shapes */ - int tot = BKE_mask_object_shape_totvert(maskobj) - 1; + int tot = BKE_mask_layer_shape_totvert(masklay) - 1; /* for interpolation */ /* TODO - assumes closed curve for now */ @@ -1646,31 +1646,31 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, } } - for (maskobj_shape = maskobj->splines_shapes.first; - maskobj_shape; - maskobj_shape = maskobj_shape->next) + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) { - if (tot == maskobj_shape->tot_vert) { + if (tot == masklay_shape->tot_vert) { float *data_resized; - maskobj_shape->tot_vert++; - data_resized = MEM_mallocN(maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + masklay_shape->tot_vert++; + data_resized = MEM_mallocN(masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); if (index > 0) { memcpy(data_resized, - maskobj_shape->data, + masklay_shape->data, index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } - if (index != maskobj_shape->tot_vert - 1) { + if (index != masklay_shape->tot_vert - 1) { memcpy(&data_resized[(index + 1) * MASK_OBJECT_SHAPE_ELEM_SIZE], - maskobj_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), - (maskobj_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + masklay_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), + (masklay_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } if (do_init) { float *fp = &data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE]; - mask_object_shape_from_mask_point(&spline->points[spline_point_index].bezt, fp); + mask_layer_shape_from_mask_point(&spline->points[spline_point_index].bezt, fp); if (do_init_interpolate && spline->tot_point > 2) { for (i = 0; i < 3; i++) { @@ -1687,12 +1687,12 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } - MEM_freeN(maskobj_shape->data); - maskobj_shape->data = data_resized; + MEM_freeN(masklay_shape->data); + masklay_shape->data = data_resized; } else { printf("%s: vert mismatch %d != %d (frame %d)\n", - __func__, maskobj_shape->tot_vert, tot, maskobj_shape->frame); + __func__, masklay_shape->tot_vert, tot, masklay_shape->frame); } } } @@ -1700,40 +1700,40 @@ void BKE_mask_object_shape_changed_add(MaskObject *maskobj, int index, /* move array to account for removed point */ -void BKE_mask_object_shape_changed_remove(MaskObject *maskobj, int index, int count) +void BKE_mask_layer_shape_changed_remove(MaskLayer *masklay, int index, int count) { - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; /* the point has already been removed in this array so add one when comparing with the shapes */ - int tot = BKE_mask_object_shape_totvert(maskobj); + int tot = BKE_mask_layer_shape_totvert(masklay); - for (maskobj_shape = maskobj->splines_shapes.first; - maskobj_shape; - maskobj_shape = maskobj_shape->next) + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) { - if (tot == maskobj_shape->tot_vert - count) { + if (tot == masklay_shape->tot_vert - count) { float *data_resized; - maskobj_shape->tot_vert -= count; - data_resized = MEM_mallocN(maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + masklay_shape->tot_vert -= count; + data_resized = MEM_mallocN(masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); if (index > 0) { memcpy(data_resized, - maskobj_shape->data, + masklay_shape->data, index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } - if (index != maskobj_shape->tot_vert) { + if (index != masklay_shape->tot_vert) { memcpy(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE], - maskobj_shape->data + ((index + count) * MASK_OBJECT_SHAPE_ELEM_SIZE), - (maskobj_shape->tot_vert - index) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + masklay_shape->data + ((index + count) * MASK_OBJECT_SHAPE_ELEM_SIZE), + (masklay_shape->tot_vert - index) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); } - MEM_freeN(maskobj_shape->data); - maskobj_shape->data = data_resized; + MEM_freeN(masklay_shape->data); + masklay_shape->data = data_resized; } else { printf("%s: vert mismatch %d != %d (frame %d)\n", - __func__, maskobj_shape->tot_vert - count, tot, maskobj_shape->frame); + __func__, masklay_shape->tot_vert - count, tot, masklay_shape->frame); } } } @@ -1775,7 +1775,7 @@ static void linear_clamp_vn_vn(float *array, const int size) /* rasterization */ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) { - MaskObject *maskobj; + MaskLayer *masklay; /* temp blending buffer */ const int buffer_size = width * height; @@ -1789,17 +1789,17 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) } max_dseg_len = 1.0f / max_dseg_len; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; float alpha; - if (maskobj->restrictflag & MASK_RESTRICT_RENDER) { + if (masklay->restrictflag & MASK_RESTRICT_RENDER) { continue; } memset(buffer_tmp, 0, sizeof(float) * buffer_size); - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { float (*diff_points)[2]; int tot_diff_point; @@ -1853,10 +1853,10 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) } /* blend with original */ - if (maskobj->blend_flag & MASK_BLENDFLAG_INVERT) { + if (masklay->blend_flag & MASK_BLENDFLAG_INVERT) { /* apply alpha multiply before inverting */ - if (maskobj->alpha != 1.0f) { - m_invert_vn_vn(buffer_tmp, maskobj->alpha, buffer_size); + if (masklay->alpha != 1.0f) { + m_invert_vn_vn(buffer_tmp, masklay->alpha, buffer_size); } else { invert_vn_vn(buffer_tmp, buffer_size); @@ -1865,10 +1865,10 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) alpha = 1.0f; } else { - alpha = maskobj->alpha; + alpha = masklay->alpha; } - switch (maskobj->blend) { + switch (masklay->blend) { case MASK_BLEND_SUBTRACT: { if (alpha == 1.0f) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9122e01fb2a..602c410dc21 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6182,19 +6182,19 @@ static void lib_link_movieclip(FileData *fd, Main *main) static void direct_link_mask(FileData *fd, Mask *mask) { - MaskObject *maskobj; + MaskLayer *masklay; mask->adt = newdataadr(fd, mask->adt); - link_list(fd, &mask->maskobjs); + link_list(fd, &mask->masklayers); - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; - link_list(fd, &maskobj->splines); + link_list(fd, &masklay->splines); - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; spline->points = newdataadr(fd, spline->points); @@ -6207,14 +6207,14 @@ static void direct_link_mask(FileData *fd, Mask *mask) } } - link_list(fd, &maskobj->splines_shapes); + link_list(fd, &masklay->splines_shapes); - for (maskobj_shape = maskobj->splines_shapes.first; maskobj_shape; maskobj_shape = maskobj_shape->next) { - maskobj_shape->data = newdataadr(fd, maskobj_shape->data); + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + masklay_shape->data = newdataadr(fd, masklay_shape->data); } - maskobj->act_spline = newdataadr(fd, maskobj->act_spline); - maskobj->act_point = newdataadr(fd, maskobj->act_point); + masklay->act_spline = newdataadr(fd, masklay->act_spline); + masklay->act_point = newdataadr(fd, masklay->act_point); } } @@ -6230,15 +6230,15 @@ static void lib_link_mask(FileData *fd, Main *main) mask = main->mask.first; while (mask) { if(mask->id.flag & LIB_NEEDLINK) { - MaskObject *maskobj; + MaskLayer *masklay; if (mask->adt) lib_link_animdata(fd, &mask->id, mask->adt); - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - spline = maskobj->splines.first; + spline = masklay->splines.first; while (spline) { int i; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 0b552ce220c..74287f0e693 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2760,20 +2760,20 @@ static void write_masks(WriteData *wd, ListBase *idbase) mask = idbase->first; while (mask) { if (mask->id.us > 0 || wd->current) { - MaskObject *maskobj; + MaskLayer *masklay; writestruct(wd, ID_MSK, "Mask", 1, mask); if (mask->adt) write_animdata(wd, mask->adt); - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; - writestruct(wd, DATA, "MaskObject", 1, maskobj); + writestruct(wd, DATA, "MaskLayer", 1, masklay); - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; void *points_deform = spline->points_deform; @@ -2792,9 +2792,9 @@ static void write_masks(WriteData *wd, ListBase *idbase) } } - for (maskobj_shape = maskobj->splines_shapes.first; maskobj_shape; maskobj_shape = maskobj_shape->next) { - writestruct(wd, DATA, "MaskObjectShape", 1, maskobj_shape); - writedata(wd, DATA, maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, maskobj_shape->data); + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + writestruct(wd, DATA, "MaskLayerShape", 1, masklay_shape); + writedata(wd, DATA, masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, masklay_shape->data); } } } diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 579527dfc56..cee8d15a807 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -188,28 +188,28 @@ static void nupdate_ak_gpframe(void *node, void *data) /* ......... */ /* Comparator callback used for ActKeyColumns and GPencil frame */ -static short compare_ak_maskobjshape(void *node, void *data) +static short compare_ak_masklayshape(void *node, void *data) { ActKeyColumn *ak = (ActKeyColumn *)node; - MaskObjectShape *maskobj_shape = (MaskObjectShape *)data; + MaskLayerShape *masklay_shape = (MaskLayerShape *)data; - if (maskobj_shape->frame < ak->cfra) + if (masklay_shape->frame < ak->cfra) return -1; - else if (maskobj_shape->frame > ak->cfra) + else if (masklay_shape->frame > ak->cfra) return 1; else return 0; } /* New node callback used for building ActKeyColumns from GPencil frames */ -static DLRBT_Node *nalloc_ak_maskobjshape(void *data) +static DLRBT_Node *nalloc_ak_masklayshape(void *data) { ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"); - MaskObjectShape *maskobj_shape = (MaskObjectShape *)data; + MaskLayerShape *masklay_shape = (MaskLayerShape *)data; /* store settings based on state of BezTriple */ - ak->cfra = maskobj_shape->frame; - ak->sel = (maskobj_shape->flag & SELECT) ? SELECT : 0; + ak->cfra = masklay_shape->frame; + ak->sel = (masklay_shape->flag & SELECT) ? SELECT : 0; /* set 'modified', since this is used to identify long keyframes */ ak->modified = 1; @@ -218,13 +218,13 @@ static DLRBT_Node *nalloc_ak_maskobjshape(void *data) } /* Node updater callback used for building ActKeyColumns from GPencil frames */ -static void nupdate_ak_maskobjshape(void *node, void *data) +static void nupdate_ak_masklayshape(void *node, void *data) { ActKeyColumn *ak = (ActKeyColumn *)node; - MaskObjectShape *maskobj_shape = (MaskObjectShape *)data; + MaskLayerShape *masklay_shape = (MaskLayerShape *)data; /* set selection status and 'touched' status */ - if (maskobj_shape->flag & SELECT) ak->sel = SELECT; + if (masklay_shape->flag & SELECT) ak->sel = SELECT; ak->modified += 1; } @@ -249,13 +249,13 @@ static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf) BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf); } -/* Add the given MaskObjectShape Frame to the given 'list' of Keyframes */ -static void add_maskobj_to_keycolumns_list(DLRBT_Tree *keys, MaskObjectShape *maskobj_shape) +/* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */ +static void add_masklay_to_keycolumns_list(DLRBT_Tree *keys, MaskLayerShape *masklay_shape) { - if (ELEM(NULL, keys, maskobj_shape)) + if (ELEM(NULL, keys, masklay_shape)) return; else - BLI_dlrbTree_add(keys, compare_ak_maskobjshape, nalloc_ak_maskobjshape, nupdate_ak_maskobjshape, maskobj_shape); + BLI_dlrbTree_add(keys, compare_ak_masklayshape, nalloc_ak_masklayshape, nupdate_ak_masklayshape, masklay_shape); } /* ActBeztColumns (Helpers for Long Keyframes) ------------------------------ */ @@ -994,16 +994,16 @@ void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys) } } -void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskObject *maskobj, DLRBT_Tree *keys) +void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *keys) { - MaskObjectShape *maskobj_shape; + MaskLayerShape *masklay_shape; - if (maskobj && keys) { - for (maskobj_shape = maskobj->splines_shapes.first; - maskobj_shape; - maskobj_shape = maskobj_shape->next) + if (masklay && keys) { + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) { - add_maskobj_to_keycolumns_list(keys, maskobj_shape); + add_masklay_to_keycolumns_list(keys, masklay_shape); } } } diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index d90b5648c23..e24c21bc133 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -42,7 +42,7 @@ struct bActionGroup; struct Object; struct ListBase; struct bGPDlayer; -struct MaskObject; +struct MaskLayer; struct Scene; struct View2D; struct DLRBT_Tree; @@ -142,7 +142,7 @@ void summary_to_keylist(struct bAnimContext *ac, struct DLRBT_Tree *keys, struct void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys); /* Mask */ // XXX not restored -void mask_to_keylist(struct bDopeSheet *UNUSED(ads), struct MaskObject *maskobj, struct DLRBT_Tree *keys); +void mask_to_keylist(struct bDopeSheet *UNUSED(ads), struct MaskLayer *masklay, struct DLRBT_Tree *keys); /* ActKeyColumn API ---------------- */ /* Comparator callback used for ActKeyColumns and cframe float-value pointer */ diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index b7dee09cbe9..0c4c2f4788c 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -42,6 +42,6 @@ void ED_operatormacros_mask(void); void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type); /* mask_shapekey.c */ -int ED_mask_object_shape_auto_key_all(struct Mask *mask, const int frame); +int ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame); #endif /* ED_TEXT_H */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index d23cd88cf05..daba096696c 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2241,7 +2241,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiItemL(split, name, ICON_OBJECT_DATA); } } - else if (itemptr->type == &RNA_MaskObject) { + else if (itemptr->type == &RNA_MaskLayer) { split = uiLayoutSplit(sub, 0.66f, 0); uiItemL(split, name, icon); diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index c282153acbf..5b8bf1075b4 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -49,11 +49,11 @@ #include "mask_intern.h" /* own include */ -static void mask_spline_color_get(MaskObject *maskobj, MaskSpline *spline, const int is_sel, +static void mask_spline_color_get(MaskLayer *masklay, MaskSpline *spline, const int is_sel, unsigned char r_rgb[4]) { if (is_sel) { - if (maskobj->act_spline == spline) { + if (masklay->act_spline == spline) { r_rgb[0] = r_rgb[1] = r_rgb[2] = 255; } else { @@ -69,7 +69,7 @@ static void mask_spline_color_get(MaskObject *maskobj, MaskSpline *spline, const r_rgb[3] = 255; } -static void mask_spline_feather_color_get(MaskObject *UNUSED(maskobj), MaskSpline *UNUSED(spline), const int is_sel, +static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline *UNUSED(spline), const int is_sel, unsigned char r_rgb[4]) { if (is_sel) { @@ -85,7 +85,7 @@ static void mask_spline_feather_color_get(MaskObject *UNUSED(maskobj), MaskSplin } #if 0 -static void draw_spline_parents(MaskObject *UNUSED(maskobj), MaskSpline *spline) +static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline) { int i; MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -119,9 +119,9 @@ static void draw_spline_parents(MaskObject *UNUSED(maskobj), MaskSpline *spline) #endif /* return non-zero if spline is selected */ -static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) +static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline) { - const int is_spline_sel = (spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0; + const int is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0; unsigned char rgb_spline[4]; MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -135,7 +135,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) glPointSize(hsize); - mask_spline_color_get(maskobj, spline, is_spline_sel, rgb_spline); + mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline); /* feather points */ feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); @@ -157,7 +157,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) } if (sel) { - if (point == maskobj->act_point) + if (point == masklay->act_point) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); @@ -201,7 +201,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) /* draw CV point */ if (MASKPOINT_ISSEL_KNOT(point)) { - if (point == maskobj->act_point) + if (point == masklay->act_point) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); @@ -216,7 +216,7 @@ static void draw_spline_points(MaskObject *maskobj, MaskSpline *spline) /* draw handle points */ if (has_handle) { if (MASKPOINT_ISSEL_HANDLE(point)) { - if (point == maskobj->act_point) + if (point == masklay->act_point) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); @@ -322,12 +322,12 @@ static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot } -static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, +static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, const char draw_flag, const char draw_type) { unsigned char rgb_tmp[4]; - const short is_spline_sel = (spline->flag & SELECT) && (maskobj->restrictflag & MASK_RESTRICT_SELECT) == 0; + const short is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0; const short is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH); int tot_diff_point; @@ -350,14 +350,14 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_feather_point, 0, 0.0f); /* draw feather */ - mask_spline_feather_color_get(maskobj, spline, is_spline_sel, rgb_tmp); + mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp); mask_draw_curve_type(spline, feather_points, tot_feather_point, TRUE, is_smooth, rgb_tmp, draw_type); MEM_freeN(feather_points); /* draw main curve */ - mask_spline_color_get(maskobj, spline, is_spline_sel, rgb_tmp); + mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp); mask_draw_curve_type(spline, diff_points, tot_diff_point, FALSE, is_smooth, rgb_tmp, draw_type); @@ -371,28 +371,28 @@ static void draw_spline_curve(MaskObject *maskobj, MaskSpline *spline, (void)draw_type; } -static void draw_maskobjs(Mask *mask, +static void draw_masklays(Mask *mask, const char draw_flag, const char draw_type) { - MaskObject *maskobj; + MaskLayer *masklay; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (masklay->restrictflag & MASK_RESTRICT_VIEW) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { /* draw curve itself first... */ - draw_spline_curve(maskobj, spline, draw_flag, draw_type); + draw_spline_curve(masklay, spline, draw_flag, draw_type); -// draw_spline_parents(maskobj, spline); +// draw_spline_parents(masklay, spline); - if (!(maskobj->restrictflag & MASK_RESTRICT_SELECT)) { + if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) { /* ...and then handles over the curve so they're nicely visible */ - draw_spline_points(maskobj, spline); + draw_spline_points(masklay, spline); } /* show undeform for testing */ @@ -400,9 +400,9 @@ static void draw_maskobjs(Mask *mask, void *back = spline->points_deform; spline->points_deform = NULL; - draw_spline_curve(maskobj, spline, draw_flag, draw_type); -// draw_spline_parents(maskobj, spline); - draw_spline_points(maskobj, spline); + draw_spline_curve(masklay, spline, draw_flag, draw_type); +// draw_spline_parents(masklay, spline); + draw_spline_points(masklay, spline); spline->points_deform = back; } } @@ -417,5 +417,5 @@ void ED_mask_draw(const bContext *C, if (!mask) return; - draw_maskobjs(mask, draw_flag, draw_type); + draw_masklays(mask, draw_flag, draw_type); } diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index a0b47be8ea3..778990726e5 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -189,9 +189,9 @@ void ED_operatortypes_mask(void) { WM_operatortype_append(MASK_OT_new); - /* mask objects */ - WM_operatortype_append(MASK_OT_object_new); - WM_operatortype_append(MASK_OT_object_remove); + /* mask layers */ + WM_operatortype_append(MASK_OT_layer_new); + WM_operatortype_append(MASK_OT_layer_remove); /* geometry */ WM_operatortype_append(MASK_OT_add_vertex); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index b17d7e7173a..5940b76abf0 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -40,8 +40,8 @@ struct wmOperatorType; /* mask_ops.c */ void MASK_OT_new(struct wmOperatorType *ot); -void MASK_OT_object_new(struct wmOperatorType *ot); -void MASK_OT_object_remove(struct wmOperatorType *ot); +void MASK_OT_layer_new(struct wmOperatorType *ot); +void MASK_OT_layer_remove(struct wmOperatorType *ot); void MASK_OT_add_vertex(struct wmOperatorType *ot); void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); @@ -58,12 +58,12 @@ void MASK_OT_handle_type_set(struct wmOperatorType *ot); int ED_mask_feather_find_nearest( struct bContext *C, struct Mask *mask, float normal_co[2], int threshold, - struct MaskObject **maskobj_r, struct MaskSpline **spline_r, struct MaskSplinePoint **point_r, + struct MaskLayer **masklay_r, struct MaskSpline **spline_r, struct MaskSplinePoint **point_r, struct MaskSplinePointUW **uw_r, float *score); struct MaskSplinePoint *ED_mask_point_find_nearest( struct bContext *C, struct Mask *mask, float normal_co[2], int threshold, - struct MaskObject **maskobj_r, struct MaskSpline **spline_r, int *is_handle_r, + struct MaskLayer **masklay_r, struct MaskSpline **spline_r, int *is_handle_r, float *score); /* mask_relationships.c */ @@ -79,10 +79,10 @@ void MASK_OT_select_lasso(struct wmOperatorType *ot); void MASK_OT_select_circle(struct wmOperatorType *ot); int ED_mask_spline_select_check(struct MaskSplinePoint *points, int tot_point); -int ED_mask_object_select_check(struct MaskObject *maskobj); +int ED_mask_layer_select_check(struct MaskLayer *masklay); int ED_mask_select_check(struct Mask *mask); -void ED_mask_object_select_set(struct MaskObject *maskobj, int select); +void ED_mask_layer_select_set(struct MaskLayer *masklay, int select); void ED_mask_select_toggle_all(struct Mask *mask, int action); void ED_mask_select_flush_all(struct Mask *mask); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 2eaae673364..e56eb181a51 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -122,11 +122,11 @@ static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, fl } MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float normal_co[2], int threshold, - MaskObject **maskobj_r, MaskSpline **spline_r, int *is_handle_r, + MaskLayer **masklay_r, MaskSpline **spline_r, int *is_handle_r, float *score) { - MaskObject *maskobj; - MaskObject *point_maskobj = NULL; + MaskLayer *masklay; + MaskLayer *point_masklay = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; float co[2], aspx, aspy; @@ -140,14 +140,14 @@ MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float norma co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i; @@ -168,7 +168,7 @@ MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float norma cur_len = len_v2v2(co, handle); if (cur_len < len) { - point_maskobj = maskobj; + point_masklay = masklay; point_spline = spline; point = cur_point; len = cur_len; @@ -180,7 +180,7 @@ MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float norma if (cur_len < len) { point_spline = spline; - point_maskobj = maskobj; + point_masklay = masklay; point = cur_point; len = cur_len; is_handle = FALSE; @@ -190,8 +190,8 @@ MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float norma } if (len < threshold) { - if (maskobj_r) - *maskobj_r = point_maskobj; + if (masklay_r) + *masklay_r = point_masklay; if (spline_r) *spline_r = point_spline; @@ -205,8 +205,8 @@ MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float norma return point; } - if (maskobj_r) - *maskobj_r = NULL; + if (masklay_r) + *masklay_r = NULL; if (spline_r) *spline_r = NULL; @@ -218,10 +218,10 @@ MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float norma } int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], int threshold, - MaskObject **maskobj_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, MaskSplinePointUW **uw_r, float *score) { - MaskObject *maskobj, *point_maskobj = NULL; + MaskLayer *masklay, *point_masklay = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; MaskSplinePointUW *uw = NULL; @@ -236,16 +236,16 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { //MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, tot_feather_point; float (*feather_points)[2], (*fp)[2]; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } @@ -269,7 +269,7 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in else uw = &cur_point->uw[j - 1]; - point_maskobj = maskobj; + point_masklay = masklay; point_spline = spline; point = cur_point; len = cur_len; @@ -284,8 +284,8 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in } if (len < threshold) { - if (maskobj_r) - *maskobj_r = point_maskobj; + if (masklay_r) + *masklay_r = point_masklay; if (spline_r) *spline_r = point_spline; @@ -302,8 +302,8 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in return TRUE; } - if (maskobj_r) - *maskobj_r = NULL; + if (masklay_r) + *masklay_r = NULL; if (spline_r) *spline_r = NULL; @@ -315,10 +315,10 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in } static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_co[2], int threshold, int feather, - MaskObject **maskobj_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, float *u_r, float tangent[2]) { - MaskObject *maskobj, *point_maskobj; + MaskLayer *masklay, *point_masklay; MaskSpline *point_spline; MaskSplinePoint *point = NULL; float dist, co[2]; @@ -333,14 +333,14 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -381,7 +381,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c if (tangent) sub_v2_v2v2(tangent, &diff_points[2 * i + 2], &diff_points[2 * i]); - point_maskobj = maskobj; + point_masklay = masklay; point_spline = spline; point = cur_point; dist = cur_dist; @@ -400,8 +400,8 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c } if (point && dist < threshold) { - if (maskobj_r) - *maskobj_r = point_maskobj; + if (masklay_r) + *masklay_r = point_masklay; if (spline_r) *spline_r = point_spline; @@ -418,8 +418,8 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c return TRUE; } - if (maskobj_r) - *maskobj_r = NULL; + if (masklay_r) + *masklay_r = NULL; if (spline_r) *spline_r = NULL; @@ -466,50 +466,50 @@ void MASK_OT_new(wmOperatorType *ot) RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask"); } -/******************** create new maskobj *********************/ +/******************** create new masklay *********************/ -static int maskobj_new_exec(bContext *C, wmOperator *op) +static int masklay_new_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); char name[MAX_ID_NAME - 2]; RNA_string_get(op->ptr, "name", name); - BKE_mask_object_new(mask, name); - mask->act_maskobj = mask->tot_maskobj - 1; + BKE_mask_layer_new(mask, name); + mask->masklay_act = mask->masklay_tot - 1; WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; } -void MASK_OT_object_new(wmOperatorType *ot) +void MASK_OT_layer_new(wmOperatorType *ot) { /* identifiers */ - ot->name = "Add Mask Object"; - ot->description = "Add new mask object for masking"; - ot->idname = "MASK_OT_object_new"; + ot->name = "Add Mask Layer"; + ot->description = "Add new mask layer for masking"; + ot->idname = "MASK_OT_layer_new"; /* api callbacks */ - ot->exec = maskobj_new_exec; + ot->exec = masklay_new_exec; ot->poll = ED_maskediting_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask object"); + RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask layer"); } -/******************** remove mask object *********************/ +/******************** remove mask layer *********************/ -static int maskobj_remove_exec(bContext *C, wmOperator *UNUSED(op)) +static int masklay_remove_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj = BKE_mask_object_active(mask); + MaskLayer *masklay = BKE_mask_layer_active(mask); - if (maskobj) { - BKE_mask_object_remove(mask, maskobj); + if (masklay) { + BKE_mask_layer_remove(mask, masklay); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); } @@ -517,15 +517,15 @@ static int maskobj_remove_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -void MASK_OT_object_remove(wmOperatorType *ot) +void MASK_OT_layer_remove(wmOperatorType *ot) { /* identifiers */ - ot->name = "Remove Mask Object"; - ot->description = "Remove mask object"; - ot->idname = "MASK_OT_object_remove"; + ot->name = "Remove Mask Layer"; + ot->description = "Remove mask layer"; + ot->idname = "MASK_OT_layer_remove"; /* api callbacks */ - ot->exec = maskobj_remove_exec; + ot->exec = masklay_remove_exec; ot->poll = ED_maskediting_poll; /* flags */ @@ -546,7 +546,7 @@ typedef struct SlidePointData { float vec[3][3]; Mask *mask; - MaskObject *maskobj; + MaskLayer *masklay; MaskSpline *spline; MaskSplinePoint *point; MaskSplinePointUW *uw; @@ -562,7 +562,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) { Mask *mask = CTX_data_edit_mask(C); SlidePointData *customdata = NULL; - MaskObject *maskobj, *cv_maskobj, *feather_maskobj; + MaskLayer *masklay, *cv_masklay, *feather_masklay; MaskSpline *spline, *cv_spline, *feather_spline; MaskSplinePoint *point, *cv_point, *feather_point; MaskSplinePointUW *uw = NULL; @@ -574,13 +574,13 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) ED_mask_mouse_pos(C, event, co); ED_mask_size(C, &width, &height); - cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_maskobj, &cv_spline, &is_handle, &cv_score); + cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &is_handle, &cv_score); - if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_maskobj, &feather_spline, &feather_point, &uw, &feather_score)) { + if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_masklay, &feather_spline, &feather_point, &uw, &feather_score)) { if (slide_feather || !cv_point || feather_score < cv_score) { action = SLIDE_ACTION_FEATHER; - maskobj = feather_maskobj; + masklay = feather_masklay; spline = feather_spline; point = feather_point; } @@ -592,7 +592,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) else action = SLIDE_ACTION_POINT; - maskobj = cv_maskobj; + masklay = cv_masklay; spline = cv_spline; point = cv_point; } @@ -601,7 +601,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data"); customdata->mask = mask; - customdata->maskobj = maskobj; + customdata->masklay = masklay; customdata->spline = spline; customdata->point = point; customdata->width = width; @@ -668,8 +668,8 @@ static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) ED_mask_select_flush_all(mask); } - slidedata->maskobj->act_spline = slidedata->spline; - slidedata->maskobj->act_point = slidedata->point; + slidedata->masklay->act_spline = slidedata->spline; + slidedata->masklay->act_point = slidedata->point; WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); @@ -794,7 +794,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) free_slide_point_data(op->customdata); if (IS_AUTOKEY_ON(scene)) { - ED_mask_object_shape_auto_key_all(data->mask, CFRA); + ED_mask_layer_shape_auto_key_all(data->mask, CFRA); } WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); @@ -986,13 +986,13 @@ static void mask_spline_add_point_at_index(MaskSpline *spline, int point_index) static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) { - MaskObject *maskobj; + MaskLayer *masklay; MaskSpline *spline; MaskSplinePoint *point = NULL; const float threshold = 9; float tangent[2]; - if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &maskobj, &spline, &point, NULL, tangent)) { + if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, NULL, tangent)) { MaskSplinePoint *new_point; int point_index = point - spline->points; @@ -1005,9 +1005,9 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) setup_vertex_point(C, mask, spline, new_point, co, tangent, NULL, TRUE); /* TODO - we could pass the spline! */ - BKE_mask_object_shape_changed_add(maskobj, BKE_mask_object_shape_spline_to_index(maskobj, spline) + point_index + 1, TRUE, TRUE); + BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index + 1, TRUE, TRUE); - maskobj->act_point = new_point; + masklay->act_point = new_point; WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1019,17 +1019,17 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) /* **** add extrude vertex **** */ -static void finSelectedSplinePoint(MaskObject *maskobj, MaskSpline **spline, MaskSplinePoint **point, short check_active) +static void finSelectedSplinePoint(MaskLayer *masklay, MaskSpline **spline, MaskSplinePoint **point, short check_active) { - MaskSpline *cur_spline = maskobj->splines.first; + MaskSpline *cur_spline = masklay->splines.first; *spline = NULL; *point = NULL; if (check_active) { - if (maskobj->act_spline && maskobj->act_point) { - *spline = maskobj->act_spline; - *point = maskobj->act_point; + if (masklay->act_spline && masklay->act_point) { + *spline = masklay->act_spline; + *point = masklay->act_point; return; } } @@ -1060,7 +1060,7 @@ static void finSelectedSplinePoint(MaskObject *maskobj, MaskSpline **spline, Mas } } -static int add_vertex_extrude(bContext *C, Mask *mask, MaskObject *maskobj, const float co[2]) +static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2]) { MaskSpline *spline; MaskSplinePoint *point; @@ -1076,11 +1076,11 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskObject *maskobj, cons ED_mask_select_toggle_all(mask, SEL_DESELECT); - if (!maskobj) { + if (!masklay) { return FALSE; } else { - finSelectedSplinePoint(maskobj, &spline, &point, TRUE); + finSelectedSplinePoint(masklay, &spline, &point, TRUE); } point_index = (point - spline->points); @@ -1141,13 +1141,13 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskObject *maskobj, cons new_point = &spline->points[point_index + 1]; } - maskobj->act_point = new_point; + masklay->act_point = new_point; setup_vertex_point(C, mask, spline, new_point, co, NULL, ref_point, FALSE); - if (maskobj->splines_shapes.first) { + if (masklay->splines_shapes.first) { point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); - BKE_mask_object_shape_changed_add(maskobj, BKE_mask_object_shape_spline_to_index(maskobj, spline) + point_index, TRUE, TRUE); + BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, TRUE, TRUE); } if (do_recalc_src) { @@ -1160,7 +1160,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskObject *maskobj, cons return TRUE; } -static int add_vertex_new(bContext *C, Mask *mask, MaskObject *maskobj, const float co[2]) +static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2]) { MaskSpline *spline; MaskSplinePoint *point; @@ -1168,32 +1168,32 @@ static int add_vertex_new(bContext *C, Mask *mask, MaskObject *maskobj, const fl ED_mask_select_toggle_all(mask, SEL_DESELECT); - if (!maskobj) { - /* if there's no maskobj currently operationg on, create new one */ - maskobj = BKE_mask_object_new(mask, ""); - mask->act_maskobj = mask->tot_maskobj - 1; + if (!masklay) { + /* if there's no masklay currently operationg on, create new one */ + masklay = BKE_mask_layer_new(mask, ""); + mask->masklay_act = mask->masklay_tot - 1; spline = NULL; point = NULL; } else { - finSelectedSplinePoint(maskobj, &spline, &point, TRUE); + finSelectedSplinePoint(masklay, &spline, &point, TRUE); } if (!spline) { - /* no selected splines in active maskobj, create new spline */ - spline = BKE_mask_spline_add(maskobj); + /* no selected splines in active masklay, create new spline */ + spline = BKE_mask_spline_add(masklay); } - maskobj->act_spline = spline; + masklay->act_spline = spline; new_point = spline->points; - maskobj->act_point = new_point; + masklay->act_point = new_point; setup_vertex_point(C, mask, spline, new_point, co, NULL, ref_point, FALSE); { int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); - BKE_mask_object_shape_changed_add(maskobj, BKE_mask_object_shape_spline_to_index(maskobj, spline) + point_index, TRUE, TRUE); + BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, TRUE, TRUE); } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1204,23 +1204,23 @@ static int add_vertex_new(bContext *C, Mask *mask, MaskObject *maskobj, const fl static int add_vertex_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; float co[2]; - maskobj = BKE_mask_object_active(mask); + masklay = BKE_mask_layer_active(mask); - if (maskobj && maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { - maskobj = NULL; + if (masklay && masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + masklay = NULL; } RNA_float_get_array(op->ptr, "location", co); - if (maskobj && maskobj->act_point && MASKPOINT_ISSEL_ANY(maskobj->act_point)) { + if (masklay && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) { /* cheap trick - double click for cyclic */ - MaskSpline *spline = maskobj->act_spline; - MaskSplinePoint *point = maskobj->act_point; + MaskSpline *spline = masklay->act_spline; + MaskSplinePoint *point = masklay->act_point; int is_sta = (point == spline->points); int is_end = (point == &spline->points[spline->tot_point - 1]); @@ -1249,14 +1249,14 @@ static int add_vertex_exec(bContext *C, wmOperator *op) } if (!add_vertex_subdivide(C, mask, co)) { - if (!add_vertex_extrude(C, mask, maskobj, co)) { + if (!add_vertex_extrude(C, mask, masklay, co)) { return OPERATOR_CANCELLED; } } } else { if (!add_vertex_subdivide(C, mask, co)) { - if (!add_vertex_new(C, mask, maskobj, co)) { + if (!add_vertex_new(C, mask, masklay, co)) { return OPERATOR_CANCELLED; } } @@ -1304,7 +1304,7 @@ void MASK_OT_add_vertex(wmOperatorType *ot) static int add_feather_vertex_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; MaskSpline *spline; MaskSplinePoint *point = NULL; const float threshold = 9; @@ -1316,7 +1316,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) if (point) return OPERATOR_FINISHED; - if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &maskobj, &spline, &point, &u, NULL)) { + if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &masklay, &spline, &point, &u, NULL)) { Scene *scene = CTX_data_scene(C); float w = BKE_mask_point_weight(spline, point, u); @@ -1370,16 +1370,16 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot) static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { spline->flag ^= MASK_SPLINE_CYCLIC; } @@ -1447,17 +1447,17 @@ static void delete_feather_points(MaskSplinePoint *point) static int delete_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; - int mask_object_shape_ofs = 0; + MaskLayer *masklay; + int mask_layer_shape_ofs = 0; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - spline = maskobj->splines.first; + spline = masklay->splines.first; while (spline) { const int tot_point_orig = spline->tot_point; @@ -1475,15 +1475,15 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) if (count == 0) { /* delete the whole spline */ - BLI_remlink(&maskobj->splines, spline); + BLI_remlink(&masklay->splines, spline); BKE_mask_spline_free(spline); - if (spline == maskobj->act_spline) { - maskobj->act_spline = NULL; - maskobj->act_point = NULL; + if (spline == masklay->act_spline) { + masklay->act_spline = NULL; + masklay->act_point = NULL; } - BKE_mask_object_shape_changed_remove(maskobj, mask_object_shape_ofs, tot_point_orig); + BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs, tot_point_orig); } else { MaskSplinePoint *new_points; @@ -1495,8 +1495,8 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) MaskSplinePoint *point = &spline->points[i]; if (!MASKPOINT_ISSEL_ANY(point)) { - if (point == maskobj->act_point) - maskobj->act_point = &new_points[j]; + if (point == masklay->act_point) + masklay->act_point = &new_points[j]; delete_feather_points(point); @@ -1504,17 +1504,17 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) j++; } else { - if (point == maskobj->act_point) - maskobj->act_point = NULL; + if (point == masklay->act_point) + masklay->act_point = NULL; BKE_mask_point_free(point); spline->tot_point--; - BKE_mask_object_shape_changed_remove(maskobj, mask_object_shape_ofs + j, 1); + BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs + j, 1); } } - mask_object_shape_ofs += spline->tot_point; + mask_layer_shape_ofs += spline->tot_point; MEM_freeN(spline->points); spline->points = new_points; @@ -1555,18 +1555,18 @@ void MASK_OT_delete(wmOperatorType *ot) static int set_handle_type_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; int handle_type = RNA_enum_get(op->ptr, "type"); - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; int i; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; @@ -1616,14 +1616,14 @@ void MASK_OT_handle_type_set(wmOperatorType *ot) static int mask_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; int changed = FALSE; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - if (maskobj->restrictflag & OB_RESTRICT_VIEW) { - ED_mask_object_select_set(maskobj, TRUE); - maskobj->restrictflag &= ~OB_RESTRICT_VIEW; + if (masklay->restrictflag & OB_RESTRICT_VIEW) { + ED_mask_layer_select_set(masklay, TRUE); + masklay->restrictflag &= ~OB_RESTRICT_VIEW; changed = 1; } } @@ -1644,7 +1644,7 @@ void MASK_OT_hide_view_clear(wmOperatorType *ot) /* identifiers */ ot->name = "Clear Restrict View"; - ot->description = "Reveal the object by setting the hide flag"; + ot->description = "Reveal the layer by setting the hide flag"; ot->idname = "MASK_OT_hide_view_clear"; /* api callbacks */ @@ -1658,33 +1658,33 @@ void MASK_OT_hide_view_clear(wmOperatorType *ot) static int mask_hide_view_set_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; const int unselected = RNA_boolean_get(op->ptr, "unselected"); int changed = FALSE; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - if (maskobj->restrictflag & MASK_RESTRICT_SELECT) { + if (masklay->restrictflag & MASK_RESTRICT_SELECT) { continue; } if (!unselected) { - if (ED_mask_object_select_check(maskobj)) { - ED_mask_object_select_set(maskobj, FALSE); + if (ED_mask_layer_select_check(masklay)) { + ED_mask_layer_select_set(masklay, FALSE); - maskobj->restrictflag |= OB_RESTRICT_VIEW; + masklay->restrictflag |= OB_RESTRICT_VIEW; changed = 1; - if (maskobj == BKE_mask_object_active(mask)) { - BKE_mask_object_active_set(mask, NULL); + if (masklay == BKE_mask_layer_active(mask)) { + BKE_mask_layer_active_set(mask, NULL); } } } else { - if (!ED_mask_object_select_check(maskobj)) { - maskobj->restrictflag |= OB_RESTRICT_VIEW; + if (!ED_mask_layer_select_check(masklay)) { + masklay->restrictflag |= OB_RESTRICT_VIEW; changed = 1; - if (maskobj == BKE_mask_object_active(mask)) { - BKE_mask_object_active_set(mask, NULL); + if (masklay == BKE_mask_layer_active(mask)) { + BKE_mask_layer_active_set(mask, NULL); } } } @@ -1705,7 +1705,7 @@ void MASK_OT_hide_view_set(wmOperatorType *ot) { /* identifiers */ ot->name = "Set Restrict View"; - ot->description = "Hide the object by setting the hide flag"; + ot->description = "Hide the layer by setting the hide flag"; ot->idname = "MASK_OT_hide_view_set"; /* api callbacks */ @@ -1715,6 +1715,6 @@ void MASK_OT_hide_view_set(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers"); } diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index bf57bce9957..8a8427c024b 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -60,17 +60,17 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; int i; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; @@ -106,7 +106,7 @@ void MASK_OT_parent_clear(wmOperatorType *ot) static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; /* parent info */ SpaceClip *sc; @@ -132,15 +132,15 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs); - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; int i; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index c204dbf0110..95c2808bc3e 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -71,15 +71,15 @@ int ED_mask_spline_select_check(MaskSplinePoint *points, int tot_point) return FALSE; } -int ED_mask_object_select_check(MaskObject *maskobj) +int ED_mask_layer_select_check(MaskLayer *masklay) { MaskSpline *spline; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { return FALSE; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { return TRUE; } @@ -90,10 +90,10 @@ int ED_mask_object_select_check(MaskObject *maskobj) int ED_mask_select_check(Mask *mask) { - MaskObject *maskobj; + MaskLayer *masklay; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - if (ED_mask_object_select_check(maskobj)) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + if (ED_mask_layer_select_check(masklay)) { return TRUE; } } @@ -101,17 +101,17 @@ int ED_mask_select_check(Mask *mask) return FALSE; } -void ED_mask_object_select_set(MaskObject *maskobj, int select) +void ED_mask_layer_select_set(MaskLayer *masklay, int select) { MaskSpline *spline; - if (maskobj->restrictflag & MASK_RESTRICT_SELECT) { + if (masklay->restrictflag & MASK_RESTRICT_SELECT) { if (select == TRUE) { return; } } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; if (select) @@ -129,7 +129,7 @@ void ED_mask_object_select_set(MaskObject *maskobj, int select) void ED_mask_select_toggle_all(Mask *mask, int action) { - MaskObject *maskobj; + MaskLayer *masklay; if (action == SEL_TOGGLE) { if (ED_mask_select_check(mask)) @@ -138,31 +138,31 @@ void ED_mask_select_toggle_all(Mask *mask, int action) action = SEL_SELECT; } - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (masklay->restrictflag & MASK_RESTRICT_VIEW) { continue; } - ED_mask_object_select_set(maskobj, (action == SEL_SELECT) ? TRUE : FALSE); + ED_mask_layer_select_set(masklay, (action == SEL_SELECT) ? TRUE : FALSE); } } void ED_mask_select_flush_all(Mask *mask) { - MaskObject *maskobj; + MaskLayer *masklay; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; spline->flag &= ~SELECT; - /* intentionally _dont_ do this in the maskobj loop + /* intentionally _dont_ do this in the masklay loop * so we clear flags on all splines */ - if (maskobj->restrictflag & MASK_RESTRICT_VIEW) { + if (masklay->restrictflag & MASK_RESTRICT_VIEW) { continue; } @@ -225,7 +225,7 @@ void MASK_OT_select_all(wmOperatorType *ot) static int select_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; MaskSpline *spline; MaskSplinePoint *point = NULL; float co[2]; @@ -238,7 +238,7 @@ static int select_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "location", co); - point = ED_mask_point_find_nearest(C, mask, co, threshold, &maskobj, &spline, &is_handle, NULL); + point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &is_handle, NULL); if (point) { if (extend == 0 && deselect == 0 && toggle == 0) @@ -246,8 +246,8 @@ static int select_exec(bContext *C, wmOperator *op) if (is_handle) { if (extend) { - maskobj->act_spline = spline; - maskobj->act_point = point; + masklay->act_spline = spline; + masklay->act_point = point; BKE_mask_point_select_set_handle(point, TRUE); } @@ -255,8 +255,8 @@ static int select_exec(bContext *C, wmOperator *op) BKE_mask_point_select_set_handle(point, FALSE); } else { - maskobj->act_spline = spline; - maskobj->act_point = point; + masklay->act_spline = spline; + masklay->act_point = point; if (!MASKPOINT_ISSEL_HANDLE(point)) { BKE_mask_point_select_set_handle(point, TRUE); @@ -268,8 +268,8 @@ static int select_exec(bContext *C, wmOperator *op) } else { if (extend) { - maskobj->act_spline = spline; - maskobj->act_point = point; + masklay->act_spline = spline; + masklay->act_point = point; BKE_mask_point_select_set(point, TRUE); } @@ -277,8 +277,8 @@ static int select_exec(bContext *C, wmOperator *op) BKE_mask_point_select_set(point, FALSE); } else { - maskobj->act_spline = spline; - maskobj->act_point = point; + masklay->act_spline = spline; + masklay->act_point = point; if (!MASKPOINT_ISSEL_ANY(point)) { BKE_mask_point_select_set(point, TRUE); @@ -289,8 +289,8 @@ static int select_exec(bContext *C, wmOperator *op) } } - maskobj->act_spline = spline; - maskobj->act_point = point; + masklay->act_spline = spline; + masklay->act_point = point; ED_mask_select_flush_all(mask); @@ -301,15 +301,15 @@ static int select_exec(bContext *C, wmOperator *op) else { MaskSplinePointUW *uw; - if (ED_mask_feather_find_nearest(C, mask, co, threshold, &maskobj, &spline, &point, &uw, NULL)) { + if (ED_mask_feather_find_nearest(C, mask, co, threshold, &masklay, &spline, &point, &uw, NULL)) { if (!extend) ED_mask_select_toggle_all(mask, SEL_DESELECT); if (uw) uw->flag |= SELECT; - maskobj->act_spline = spline; - maskobj->act_point = point; + masklay->act_spline = spline; + masklay->act_point = point; ED_mask_select_flush_all(mask); @@ -362,7 +362,7 @@ void MASK_OT_select(wmOperatorType *ot) static int border_select_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; int i; rcti rect; @@ -382,14 +382,14 @@ static int border_select_exec(bContext *C, wmOperator *op) extend = RNA_boolean_get(op->ptr, "extend"); /* do actual selection */ - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); for (i = 0; i < spline->tot_point; i++) { @@ -447,7 +447,7 @@ void MASK_OT_select_border(wmOperatorType *ot) static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short select) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; int i; rcti rect; @@ -457,14 +457,14 @@ static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short BLI_lasso_boundbox(&rect, mcords, moves); /* do actual selection */ - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); for (i = 0; i < spline->tot_point; i++) { @@ -559,7 +559,7 @@ static int mask_spline_point_inside_ellipse(BezTriple *bezt, float offset[2], fl static int circle_select_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; int i; SpaceClip *sc = CTX_wm_space_clip(C); @@ -586,14 +586,14 @@ static int circle_select_exec(bContext *C, wmOperator *op) ED_mask_point_pos(C, x, y, &offset[0], &offset[1]); /* do actual selection */ - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); for (i = 0; i < spline->tot_point; i++) { diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index e323a6abe15..94aebb9f3a1 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -61,18 +61,18 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); const int frame = CFRA; Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; int change = FALSE; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskObjectShape *maskobj_shape; + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskLayerShape *masklay_shape; - if (!ED_mask_object_select_check(maskobj)) { + if (!ED_mask_layer_select_check(masklay)) { continue; } - maskobj_shape = BKE_mask_object_shape_varify_frame(maskobj, frame); - BKE_mask_object_shape_from_mask(maskobj, maskobj_shape); + masklay_shape = BKE_mask_layer_shape_varify_frame(masklay, frame); + BKE_mask_layer_shape_from_mask(masklay, masklay_shape); change = TRUE; } @@ -107,20 +107,20 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); const int frame = CFRA; Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; int change = FALSE; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskObjectShape *maskobj_shape; + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskLayerShape *masklay_shape; - if (!ED_mask_object_select_check(maskobj)) { + if (!ED_mask_layer_select_check(masklay)) { continue; } - maskobj_shape = BKE_mask_object_shape_find_frame(maskobj, frame); + masklay_shape = BKE_mask_layer_shape_find_frame(masklay, frame); - if (maskobj_shape) { - BKE_mask_object_shape_unlink(maskobj, maskobj_shape); + if (masklay_shape) { + BKE_mask_layer_shape_unlink(masklay, masklay_shape); change = TRUE; } } @@ -151,16 +151,16 @@ void MASK_OT_shape_key_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -int ED_mask_object_shape_auto_key_all(Mask *mask, const int frame) +int ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame) { - MaskObject *maskobj; + MaskLayer *masklay; int change = FALSE; - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskObjectShape *maskobj_shape; + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskLayerShape *masklay_shape; - maskobj_shape = BKE_mask_object_shape_varify_frame(maskobj, frame); - BKE_mask_object_shape_from_mask(maskobj, maskobj_shape); + masklay_shape = BKE_mask_layer_shape_varify_frame(masklay, frame); + BKE_mask_layer_shape_from_mask(masklay, masklay_shape); change = TRUE; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 7caff30807d..89c7896d53c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1952,8 +1952,8 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) SpaceClip *sc = CTX_wm_space_clip(C); if (sc) { if ((sc->mode == SC_MODE_MASKEDITING) && sc->mask) { - MaskObject *maskobj = BKE_mask_object_active(sc->mask); - mask_to_keylist(&ads, maskobj, &keys); + MaskLayer *masklay = BKE_mask_layer_active(sc->mask); + mask_to_keylist(&ads, masklay, &keys); } } } diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index fd47bc376c7..003fa5c5cef 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -199,18 +199,18 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc /* movie clip animation */ if ((sc->mode == SC_MODE_MASKEDITING) && sc->mask) { - MaskObject *maskobj = BKE_mask_object_active(sc->mask); - if (maskobj) { - MaskObjectShape *maskobj_shape; + MaskLayer *masklay = BKE_mask_layer_active(sc->mask); + if (masklay) { + MaskLayerShape *masklay_shape; glColor4ub(255, 175, 0, 255); glBegin(GL_LINES); - for (maskobj_shape = maskobj->splines_shapes.first; - maskobj_shape; - maskobj_shape = maskobj_shape->next) + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) { - i = maskobj_shape->frame; + i = masklay_shape->frame; /* glRecti((i - sfra) * framelen, 0, (i - sfra + 1) * framelen, 4); */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 8211df67b17..23a88e6e547 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4915,7 +4915,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (IS_AUTOKEY_ON(t->scene)) { Scene *scene = t->scene; - ED_mask_object_shape_auto_key_all(mask, CFRA); + ED_mask_layer_shape_auto_key_all(mask, CFRA); } } } @@ -5974,7 +5974,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) { SpaceClip *sc = CTX_wm_space_clip(C); Mask *mask = CTX_data_edit_mask(C); - MaskObject *maskobj; + MaskLayer *masklay; TransData *td = NULL; TransData2D *td2d = NULL; TransDataMasking *tdm = NULL; @@ -5982,14 +5982,14 @@ static void createTransMaskingData(bContext *C, TransInfo *t) int propmode = t->flag & T_PROP_EDIT; /* count */ - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline = maskobj->splines.first; + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline = masklay->splines.first; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { @@ -6021,14 +6021,14 @@ static void createTransMaskingData(bContext *C, TransInfo *t) t->flag |= T_FREE_CUSTOMDATA; /* create data */ - for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) { - MaskSpline *spline = maskobj->splines.first; + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline = masklay->splines.first; - if (maskobj->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { int i; for (i = 0; i < spline->tot_point; i++) { diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index d677239e300..28fc9466613 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -43,9 +43,9 @@ typedef struct Mask { ID id; struct AnimData *adt; - ListBase maskobjs; /* mask objects */ - int act_maskobj; /* index of active mask object (-1 == None) */ - int tot_maskobj; /* total number of mask objects */ + ListBase masklayers; /* mask layers */ + int masklay_act; /* index of active mask layer (-1 == None) */ + int masklay_tot; /* total number of mask layers */ } Mask; typedef struct MaskParent { @@ -54,7 +54,7 @@ typedef struct MaskParent { ID *id; /* ID block of entity to which mask/spline is parented to * in case of parenting to movie tracking data set to MovieClip datablock */ char parent[64]; /* entity of parent to which parenting happened - * in case of parenting to movie tracking data contains name of object */ + * in case of parenting to movie tracking data contains name of layer */ char sub_parent[64]; /* sub-entity of parent to which parenting happened * in case of parenting to movie tracking data contains name of track */ float parent_orig[2]; /* track location at the moment of parenting */ @@ -87,22 +87,22 @@ typedef struct MaskSpline { } MaskSpline; /* one per frame */ -typedef struct MaskObjectShape { - struct MaskObjectShape *next, *prev; +typedef struct MaskLayerShape { + struct MaskLayerShape *next, *prev; float *data; /* u coordinate along spline segment and weight of this point */ int tot_vert; /* to ensure no buffer overruns's: alloc size is (tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE) */ int frame; /* different flags of this point */ char flag; char pad[7]; -} MaskObjectShape; +} MaskLayerShape; -typedef struct MaskObject { - struct MaskObject *next, *prev; +typedef struct MaskLayer { + struct MaskLayer *next, *prev; - char name[64]; /* name of the mask object (64 = MAD_ID_NAME - 2) */ + char name[64]; /* name of the mask layer (64 = MAD_ID_NAME - 2) */ - ListBase splines; /* list of splines which defines this mask object */ + ListBase splines; /* list of splines which defines this mask layer */ ListBase splines_shapes; struct MaskSpline *act_spline; /* active spline */ @@ -116,7 +116,7 @@ typedef struct MaskObject { //char flag; /* not used yet */ char restrictflag; /* matching 'Object' flag of the same name - eventually use in the outliner */ char pad[1]; -} MaskObject; +} MaskLayer; /* MaskParent->flag */ #define MASK_PARENT_ACTIVE (1 << 0) @@ -148,13 +148,13 @@ enum { MASK_DT_WHITE }; -/* maskobj->blend */ +/* masklay->blend */ enum { MASK_BLEND_ADD = 0, MASK_BLEND_SUBTRACT = 1 }; -/* maskobj->blend_flag */ +/* masklay->blend_flag */ enum { MASK_BLENDFLAG_INVERT = (1 << 0) }; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 9c465619b95..319e93b3084 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -306,7 +306,7 @@ extern StructRNA RNA_MaterialSubsurfaceScattering; extern StructRNA RNA_MaterialTextureSlot; extern StructRNA RNA_MaterialVolume; extern StructRNA RNA_Mask; -extern StructRNA RNA_MaskObject; +extern StructRNA RNA_MaskLayer; extern StructRNA RNA_Menu; extern StructRNA RNA_Mesh; extern StructRNA RNA_MeshColor; diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index c072676b665..c356cae81af 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -93,114 +93,114 @@ static void rna_MaskParent_id_type_set(PointerRNA *ptr, int value) mpar->id = NULL; } -static void rna_Mask_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +static void rna_Mask_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Mask *mask = (Mask *)ptr->id.data; - rna_iterator_listbase_begin(iter, &mask->maskobjs, NULL); + rna_iterator_listbase_begin(iter, &mask->masklayers, NULL); } -static int rna_Mask_object_active_index_get(PointerRNA *ptr) +static int rna_Mask_layer_active_index_get(PointerRNA *ptr) { Mask *mask = (Mask *)ptr->id.data; - return mask->act_maskobj; + return mask->masklay_act; } -static void rna_Mask_object_active_index_set(PointerRNA *ptr, int value) +static void rna_Mask_layer_active_index_set(PointerRNA *ptr, int value) { Mask *mask = (Mask *)ptr->id.data; - mask->act_maskobj = value; + mask->masklay_act = value; } -static void rna_Mask_object_active_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) +static void rna_Mask_layer_active_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { Mask *mask = (Mask *)ptr->id.data; *min = 0; - *max = mask->tot_maskobj - 1; + *max = mask->masklay_tot - 1; *max = MAX2(0, *max); *softmin = *min; *softmax = *max; } -static char *rna_MaskObject_path(PointerRNA *ptr) +static char *rna_MaskLayer_path(PointerRNA *ptr) { - return BLI_sprintfN("objects[\"%s\"]", ((MaskObject *)ptr->data)->name); + return BLI_sprintfN("layers[\"%s\"]", ((MaskLayer *)ptr->data)->name); } -static PointerRNA rna_Mask_object_active_get(PointerRNA *ptr) +static PointerRNA rna_Mask_layer_active_get(PointerRNA *ptr) { Mask *mask = (Mask *)ptr->id.data; - MaskObject *maskobj = BKE_mask_object_active(mask); + MaskLayer *masklay = BKE_mask_layer_active(mask); - return rna_pointer_inherit_refine(ptr, &RNA_MaskObject, maskobj); + return rna_pointer_inherit_refine(ptr, &RNA_MaskLayer, masklay); } -static void rna_Mask_object_active_set(PointerRNA *ptr, PointerRNA value) +static void rna_Mask_layer_active_set(PointerRNA *ptr, PointerRNA value) { Mask *mask = (Mask *)ptr->id.data; - MaskObject *maskobj = (MaskObject *)value.data; + MaskLayer *masklay = (MaskLayer *)value.data; - BKE_mask_object_active_set(mask, maskobj); + BKE_mask_layer_active_set(mask, masklay); } -static void rna_MaskObject_splines_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +static void rna_MaskLayer_splines_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - MaskObject *maskobj = (MaskObject *)ptr->data; + MaskLayer *masklay = (MaskLayer *)ptr->data; - rna_iterator_listbase_begin(iter, &maskobj->splines, NULL); + rna_iterator_listbase_begin(iter, &masklay->splines, NULL); } -void rna_MaskObject_name_set(PointerRNA *ptr, const char *value) +void rna_MaskLayer_name_set(PointerRNA *ptr, const char *value) { Mask *mask = (Mask *)ptr->id.data; - MaskObject *maskobj = (MaskObject *)ptr->data; + MaskLayer *masklay = (MaskLayer *)ptr->data; - BLI_strncpy(maskobj->name, value, sizeof(maskobj->name)); + BLI_strncpy(masklay->name, value, sizeof(masklay->name)); - BKE_mask_object_unique_name(mask, maskobj); + BKE_mask_layer_unique_name(mask, masklay); } -static PointerRNA rna_MaskObject_active_spline_get(PointerRNA *ptr) +static PointerRNA rna_MaskLayer_active_spline_get(PointerRNA *ptr) { - MaskObject *maskobj = (MaskObject *)ptr->data; + MaskLayer *masklay = (MaskLayer *)ptr->data; - return rna_pointer_inherit_refine(ptr, &RNA_MaskSpline, maskobj->act_spline); + return rna_pointer_inherit_refine(ptr, &RNA_MaskSpline, masklay->act_spline); } -static void rna_MaskObject_active_spline_set(PointerRNA *ptr, PointerRNA value) +static void rna_MaskLayer_active_spline_set(PointerRNA *ptr, PointerRNA value) { - MaskObject *maskobj = (MaskObject *)ptr->data; + MaskLayer *masklay = (MaskLayer *)ptr->data; MaskSpline *spline = (MaskSpline *)value.data; - int index = BLI_findindex(&maskobj->splines, spline); + int index = BLI_findindex(&masklay->splines, spline); if (index >= 0) - maskobj->act_spline = spline; + masklay->act_spline = spline; else - maskobj->act_spline = NULL; + masklay->act_spline = NULL; } -static PointerRNA rna_MaskObject_active_spline_point_get(PointerRNA *ptr) +static PointerRNA rna_MaskLayer_active_spline_point_get(PointerRNA *ptr) { - MaskObject *maskobj = (MaskObject *)ptr->data; + MaskLayer *masklay = (MaskLayer *)ptr->data; - return rna_pointer_inherit_refine(ptr, &RNA_MaskSplinePoint, maskobj->act_point); + return rna_pointer_inherit_refine(ptr, &RNA_MaskSplinePoint, masklay->act_point); } -static void rna_MaskObject_active_spline_point_set(PointerRNA *ptr, PointerRNA value) +static void rna_MaskLayer_active_spline_point_set(PointerRNA *ptr, PointerRNA value) { - MaskObject *maskobj = (MaskObject *)ptr->data; + MaskLayer *masklay = (MaskLayer *)ptr->data; MaskSpline *spline; MaskSplinePoint *point = (MaskSplinePoint *)value.data; - maskobj->act_point = NULL; + masklay->act_point = NULL; - for (spline = maskobj->splines.first; spline; spline = spline->next) { + for (spline = masklay->splines.first; spline; spline = spline->next) { if (point >= spline->points && point < spline->points + spline->tot_point) { - maskobj->act_point = point; + masklay->act_point = point; break; } @@ -285,29 +285,29 @@ static void rna_MaskSplinePoint_handle_type_set(PointerRNA *ptr, int value) /* ** API ** */ -static MaskObject *rna_Mask_object_new(Mask *mask, const char *name) +static MaskLayer *rna_Mask_layer_new(Mask *mask, const char *name) { - MaskObject *maskobj = BKE_mask_object_new(mask, name); + MaskLayer *masklay = BKE_mask_layer_new(mask, name); WM_main_add_notifier(NC_MASK|NA_EDITED, mask); - return maskobj; + return masklay; } -void rna_Mask_object_remove(Mask *mask, MaskObject *maskobj) +void rna_Mask_layer_remove(Mask *mask, MaskLayer *masklay) { - BKE_mask_object_remove(mask, maskobj); + BKE_mask_layer_remove(mask, masklay); WM_main_add_notifier(NC_MASK|NA_EDITED, mask); } -static void rna_MaskObject_spline_add(ID *id, MaskObject *maskobj, int number) +static void rna_MaskLayer_spline_add(ID *id, MaskLayer *masklay, int number) { Mask *mask = (Mask*) id; int i; for (i = 0; i < number; i++) - BKE_mask_spline_add(maskobj); + BKE_mask_spline_add(masklay); WM_main_add_notifier(NC_MASK|NA_EDITED, mask); } @@ -330,7 +330,7 @@ static void rna_def_maskParent(BlenderRNA *brna) prop = RNA_def_property(srna, "use_parent", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_PARENT_ACTIVE); - RNA_def_property_ui_text(prop, "Use Parent", "Use parenting for this object"); + RNA_def_property_ui_text(prop, "Use Parent", "Use parenting for this layer"); RNA_def_property_update(prop, 0, "rna_Mask_update_data"); /* Target Properties - ID-block to Drive */ @@ -460,27 +460,27 @@ static void rna_def_mask_splines(BlenderRNA *brna) PropertyRNA *prop; srna = RNA_def_struct(brna, "MaskSplines", NULL); - RNA_def_struct_sdna(srna, "MaskObject"); + RNA_def_struct_sdna(srna, "MaskLayer"); RNA_def_struct_ui_text(srna, "Mask Splines", "Collection of masking splines"); - func = RNA_def_function(srna, "add", "rna_MaskObject_spline_add"); + func = RNA_def_function(srna, "add", "rna_MaskLayer_spline_add"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); - RNA_def_function_ui_description(func, "Add a number of splines to mask object"); - RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of splines to add to the object", 0, INT_MAX); + RNA_def_function_ui_description(func, "Add a number of splines to mask layer"); + RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of splines to add to the layer", 0, INT_MAX); /* active spline */ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "MaskSpline"); - RNA_def_property_pointer_funcs(prop, "rna_MaskObject_active_spline_get", "rna_MaskObject_active_spline_set", NULL, NULL); + RNA_def_property_pointer_funcs(prop, "rna_MaskLayer_active_spline_get", "rna_MaskLayer_active_spline_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); - RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking object"); + RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking layer"); /* active point */ prop = RNA_def_property(srna, "active_point", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "MaskSplinePoint"); - RNA_def_property_pointer_funcs(prop, "rna_MaskObject_active_spline_point_get", "rna_MaskObject_active_spline_point_set", NULL, NULL); + RNA_def_property_pointer_funcs(prop, "rna_MaskLayer_active_spline_point_get", "rna_MaskLayer_active_spline_point_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); - RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking object"); + RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking layer"); } static void rna_def_maskSpline(BlenderRNA *brna) @@ -514,9 +514,9 @@ static void rna_def_maskSpline(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Mask_update_data"); } -static void rna_def_mask_object(BlenderRNA *brna) +static void rna_def_mask_layer(BlenderRNA *brna) { - static EnumPropertyItem maskobj_blend_mode_items[] = { + static EnumPropertyItem masklay_blend_mode_items[] = { {MASK_BLEND_ADD, "ADD", 0, "Add", ""}, {MASK_BLEND_SUBTRACT, "SUBTRACT", 0, "Subtract", ""}, {0, NULL, 0, NULL, NULL} @@ -528,23 +528,23 @@ static void rna_def_mask_object(BlenderRNA *brna) rna_def_maskSpline(brna); rna_def_mask_splines(brna); - srna = RNA_def_struct(brna, "MaskObject", NULL); - RNA_def_struct_ui_text(srna, "Mask Object", "Single object used for masking pixels"); - RNA_def_struct_path_func(srna, "rna_MaskObject_path"); + srna = RNA_def_struct(brna, "MaskLayer", NULL); + RNA_def_struct_ui_text(srna, "Mask Layer", "Single layer used for masking pixels"); + RNA_def_struct_path_func(srna, "rna_MaskLayer_path"); /* name */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); - RNA_def_property_ui_text(prop, "Name", "Unique name of object"); - RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MaskObject_name_set"); + RNA_def_property_ui_text(prop, "Name", "Unique name of layer"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MaskLayer_name_set"); RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2); RNA_def_property_update(prop, 0, "rna_Mask_update_data"); RNA_def_struct_name_property(srna, prop); /* splines */ prop = RNA_def_property(srna, "splines", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_funcs(prop, "rna_MaskObject_splines_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_collection_funcs(prop, "rna_MaskLayer_splines_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); RNA_def_property_struct_type(prop, "MaskSpline"); - RNA_def_property_ui_text(prop, "Splines", "Collection of splines which defines this object"); + RNA_def_property_ui_text(prop, "Splines", "Collection of splines which defines this layer"); RNA_def_property_srna(prop, "MaskSplines"); /* restrict */ @@ -576,8 +576,8 @@ static void rna_def_mask_object(BlenderRNA *brna) /* weight interpolation */ prop = RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "blend"); - RNA_def_property_enum_items(prop, maskobj_blend_mode_items); - RNA_def_property_ui_text(prop, "Blend", "Method of blending mask objects"); + RNA_def_property_enum_items(prop, masklay_blend_mode_items); + RNA_def_property_ui_text(prop, "Blend", "Method of blending mask layers"); RNA_def_property_update(prop, 0, "rna_Mask_update_data"); RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); @@ -588,7 +588,7 @@ static void rna_def_mask_object(BlenderRNA *brna) } -static void rna_def_maskobjects(BlenderRNA *brna, PropertyRNA *cprop) +static void rna_def_masklayers(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; PropertyRNA *prop; @@ -596,27 +596,27 @@ static void rna_def_maskobjects(BlenderRNA *brna, PropertyRNA *cprop) FunctionRNA *func; PropertyRNA *parm; - RNA_def_property_srna(cprop, "MaskObjects"); - srna = RNA_def_struct(brna, "MaskObjects", NULL); + RNA_def_property_srna(cprop, "MaskLayers"); + srna = RNA_def_struct(brna, "MaskLayers", NULL); RNA_def_struct_sdna(srna, "Mask"); - RNA_def_struct_ui_text(srna, "Mask Objects", "Collection of objects used by mask"); + RNA_def_struct_ui_text(srna, "Mask Layers", "Collection of layers used by mask"); - func = RNA_def_function(srna, "new", "rna_Mask_object_new"); - RNA_def_function_ui_description(func, "Add object to this mask"); - RNA_def_string(func, "name", "", 0, "Name", "Name of new object"); - parm = RNA_def_pointer(func, "object", "MaskObject", "", "New mask object"); + func = RNA_def_function(srna, "new", "rna_Mask_layer_new"); + RNA_def_function_ui_description(func, "Add layer to this mask"); + RNA_def_string(func, "name", "", 0, "Name", "Name of new layer"); + parm = RNA_def_pointer(func, "layer", "MaskLayer", "", "New mask layer"); RNA_def_function_return(func, parm); - func = RNA_def_function(srna, "remove", "rna_Mask_object_remove"); - RNA_def_function_ui_description(func, "Remove object from this mask"); - RNA_def_pointer(func, "object", "MaskObject", "", "Shape to be removed"); + func = RNA_def_function(srna, "remove", "rna_Mask_layer_remove"); + RNA_def_function_ui_description(func, "Remove layer from this mask"); + RNA_def_pointer(func, "layer", "MaskLayer", "", "Shape to be removed"); - /* active object */ + /* active layer */ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "MaskObject"); - RNA_def_property_pointer_funcs(prop, "rna_Mask_object_active_get", "rna_Mask_object_active_set", NULL, NULL); + RNA_def_property_struct_type(prop, "MaskLayer"); + RNA_def_property_pointer_funcs(prop, "rna_Mask_layer_active_get", "rna_Mask_layer_active_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); - RNA_def_property_ui_text(prop, "Active Shape", "Active object in this mask"); + RNA_def_property_ui_text(prop, "Active Shape", "Active layer in this mask"); } static void rna_def_mask(BlenderRNA *brna) @@ -624,25 +624,25 @@ static void rna_def_mask(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - rna_def_mask_object(brna); + rna_def_mask_layer(brna); srna = RNA_def_struct(brna, "Mask", "ID"); RNA_def_struct_ui_text(srna, "Mask", "Mask datablock defining mask for compositing"); RNA_def_struct_ui_icon(srna, ICON_MOD_MASK); - /* mask objects */ - prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_funcs(prop, "rna_Mask_objects_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); - RNA_def_property_struct_type(prop, "MaskObject"); - RNA_def_property_ui_text(prop, "Objects", "Collection of objects which defines this mask"); - rna_def_maskobjects(brna, prop); + /* mask layers */ + prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_Mask_layers_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_struct_type(prop, "MaskLayer"); + RNA_def_property_ui_text(prop, "Layers", "Collection of layers which defines this mask"); + rna_def_masklayers(brna, prop); - /* active maskobj index */ - prop = RNA_def_property(srna, "active_object_index", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "act_maskobj"); + /* active masklay index */ + prop = RNA_def_property(srna, "active_layer_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "masklay_act"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_int_funcs(prop, "rna_Mask_object_active_index_get", "rna_Mask_object_active_index_set", "rna_Mask_object_active_index_range"); - RNA_def_property_ui_text(prop, "Active Shape Index", "Index of active object in list of all mask's objects"); + RNA_def_property_int_funcs(prop, "rna_Mask_layer_active_index_get", "rna_Mask_layer_active_index_set", "rna_Mask_layer_active_index_range"); + RNA_def_property_ui_text(prop, "Active Shape Index", "Index of active layer in list of all mask's layers"); /* pointers */ rna_def_animdata_common(srna); From 1abbb21fee7dea1ed5dfa9e6c60d531510c20538 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Thu, 31 May 2012 19:17:17 +0000 Subject: [PATCH 143/183] fixed gradient visual stepping in mask feather regions. converted all distance calculations from int to float. --- intern/raskter/raskter.c | 50 +++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index fd274c5f5f5..33da097f063 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -434,8 +434,8 @@ int PLX_raskterize(float (*base_verts)[2], int num_base_verts, * if it ends up being coupled with this function. */ int rast_scan_feather(struct r_fill_context *ctx, - struct poly_vert *base_verts, int num_base_verts, - struct poly_vert *feather_verts, int num_feather_verts) + float (*base_verts_f)[2], int num_base_verts, + struct poly_vert *feather_verts, float (*feather_verts_f)[2], int num_feather_verts) { int x_curr; /* current pixel position in X */ int y_curr; /* current scan line being drawn */ @@ -451,19 +451,19 @@ int rast_scan_feather(struct r_fill_context *ctx, /* from dem */ int a; // a = temporary pixel index buffer loop counter - int fsz; // size of the frame + float fsz; // size of the frame unsigned int rsl; // long used for finding fast 1.0/sqrt float rsf; // float used for finding fast 1.0/sqrt const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt //unsigned int gradientFillOffset; - unsigned int t; - unsigned int ud; // ud = unscaled edge distance - unsigned int dmin; // dmin = minimun edge distance + float t; + float ud; // ud = unscaled edge distance + float dmin; // dmin = minimun edge distance float odist; // odist = current outer edge distance float idist; // idist = current inner edge distance - int dx; // dx = X-delta (used for distance proportion calculation) - int dy; // dy = Y-delta (used for distance proportion calculation) + float dx; // dx = X-delta (used for distance proportion calculation) + float dy; // dy = Y-delta (used for distance proportion calculation) /* @@ -595,41 +595,43 @@ int rast_scan_feather(struct r_fill_context *ctx, /* * Begin modified code from double edge mask compo node... */ - t = (cpxl - spxl) % ctx->rb.sizex; // calculate column of pixel + t = ((float)((cpxl - spxl) % ctx->rb.sizex) + 0.5f) * (1.0f / (float)(ctx->rb.sizex)); // calculate column of pixel - fsz = y_curr; // calculate row of pixel + fsz = ((float)(y_curr) + 0.5) * (1.0f / (float)(ctx->rb.sizey)); // calculate row of pixel - dmin = 0xffffffff; // reset min distance to edge pixel + dmin = 2.0f; // reset min distance to edge pixel for (a = 0; a < num_feather_verts; a++) { // loop through all outer edge buffer pixels - dy = t - feather_verts[a].x; // set dx to gradient pixel column - outer edge pixel row - dx = fsz - feather_verts[a].y; // set dy to gradient pixel row - outer edge pixel column + dy = t - feather_verts_f[a][0]; // set dx to gradient pixel column - outer edge pixel row + dx = fsz - feather_verts_f[a][1]; // set dy to gradient pixel row - outer edge pixel column ud = dx * dx + dy * dy; // compute sum of squares if (ud < dmin) { // if our new sum of squares is less than the current minimum dmin = ud; // set a new minimum equal to the new lower value } } - odist = (float)(dmin); // cast outer min to a float + odist = dmin; // cast outer min to a float rsf = odist * 0.5f; // rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate odist = *(float *)&rsl; // reciprocal square root odist = odist * (rsopf - (rsf * odist * odist)); // -- ** this line can be iterated for more accuracy ** -- - dmin = 0xffffffff; // reset min distance to edge pixel + odist = odist * (rsopf - (rsf * odist * odist)); + dmin = 2.0f; // reset min distance to edge pixel for (a = 0; a < num_base_verts; a++) { // loop through all inside edge pixels - dy = t - base_verts[a].x; // compute delta in Y from gradient pixel to inside edge pixel - dx = fsz - base_verts[a].y; // compute delta in X from gradient pixel to inside edge pixel + dy = t - base_verts_f[a][0]; // compute delta in Y from gradient pixel to inside edge pixel + dx = fsz - base_verts_f[a][1]; // compute delta in X from gradient pixel to inside edge pixel ud = dx * dx + dy * dy; // compute sum of squares if (ud < dmin) { // if our new sum of squares is less than the current minimum we've found dmin = ud; // set a new minimum equal to the new lower value } } - idist = (float)(dmin); // cast inner min to a float + idist = dmin; // cast inner min to a float rsf = idist * 0.5f; // rsl = *(unsigned int *)&idist; // rsl = 0x5f3759df - (rsl >> 1); // see notes above idist = *(float *)&rsl; // idist = idist * (rsopf - (rsf * idist * idist)); // + idist = idist * (rsopf - (rsf * idist * idist)); /* * Note once again that since we are using reciprocals of distance values our * proportion is already the correct intensity, and does not need to be @@ -722,7 +724,6 @@ int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*f float *buf, int buf_x, int buf_y) { int i; /* i: Loop counter. */ - struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ struct poly_vert *fe; /* fe: Pointer to a list of integer buffer-space feather vertex coords. */ struct r_fill_context ctx = {0}; @@ -737,10 +738,6 @@ int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*f * In the event of a failure to allocate the memory, return 0, so this error can * be distinguished as a memory allocation error. */ - if ((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_base_verts))) == NULL) { - return(0); - } - if ((fe = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_feather_verts))) == NULL) { return(0); } @@ -753,10 +750,6 @@ int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*f * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel * drawn will be 1.0f in value, there is no anti-aliasing. */ - for (i = 0; i < num_base_verts; i++) { /* Loop over all verts. */ - ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ - ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */ - } for (i = 0; i < num_feather_verts; i++) { /* Loop over all verts. */ fe[i].x = (int)((feather_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ fe[i].y = (int)((feather_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */ @@ -767,8 +760,7 @@ int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*f ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ /* Call our rasterizer, passing in the integer coords for each vert. */ - i = rast_scan_feather(&ctx, ply, num_base_verts, fe, num_feather_verts); - free(ply); /* Free the memory allocated for the integer coordinate table. */ + i = rast_scan_feather(&ctx, base_verts, num_base_verts, fe, feather_verts, num_feather_verts); free(fe); return i; /* Return the value returned by the rasterizer. */ } From 34c52b010e914578982142a70b80e14357e4c831 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Thu, 31 May 2012 19:53:35 +0000 Subject: [PATCH 144/183] speedup normalized buffer space pixel position calculations... now incremental adds rather than full per pixel evaluation. --- intern/raskter/raskter.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 33da097f063..3d1785e2263 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -464,7 +464,8 @@ int rast_scan_feather(struct r_fill_context *ctx, float idist; // idist = current inner edge distance float dx; // dx = X-delta (used for distance proportion calculation) float dy; // dy = Y-delta (used for distance proportion calculation) - + float xpxw; + float ypxh; /* * If the number of verts specified to render as a polygon is less than 3, @@ -587,17 +588,21 @@ int rast_scan_feather(struct r_fill_context *ctx, mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { + xpxw = (1.0f / (float)(ctx->rb.sizex)); + ypxh = (1.0f / (float)(ctx->rb.sizey)); + t = ((float)((cpxl - spxl) % ctx->rb.sizex) + 0.5f) * xpxw; + fsz = ((float)(y_curr) + 0.5f) * ypxh; /* draw the pixels. */ - for (; cpxl <= mpxl; cpxl++) { + for (; cpxl <= mpxl; cpxl++, t += xpxw) { //do feather check // first check that pixel isn't already full, and only operate if it is not if (*cpxl < 0.9999f) { /* * Begin modified code from double edge mask compo node... */ - t = ((float)((cpxl - spxl) % ctx->rb.sizex) + 0.5f) * (1.0f / (float)(ctx->rb.sizex)); // calculate column of pixel + //t = ((float)((cpxl - spxl) % ctx->rb.sizex) + 0.5f) * (1.0f / (float)(ctx->rb.sizex)); // calculate column of pixel - fsz = ((float)(y_curr) + 0.5) * (1.0f / (float)(ctx->rb.sizey)); // calculate row of pixel + //fsz = ((float)(y_curr) + 0.5) * (1.0f / (float)(ctx->rb.sizey)); // calculate row of pixel dmin = 2.0f; // reset min distance to edge pixel From 05ff63b09d9804a7699dd38d3b79bb6064904fde Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Thu, 31 May 2012 20:58:46 +0000 Subject: [PATCH 145/183] code and comment cleanup in feather region drawing code --- intern/raskter/raskter.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 3d1785e2263..e30df66648b 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -597,13 +597,6 @@ int rast_scan_feather(struct r_fill_context *ctx, //do feather check // first check that pixel isn't already full, and only operate if it is not if (*cpxl < 0.9999f) { -/* - * Begin modified code from double edge mask compo node... - */ - //t = ((float)((cpxl - spxl) % ctx->rb.sizex) + 0.5f) * (1.0f / (float)(ctx->rb.sizex)); // calculate column of pixel - - //fsz = ((float)(y_curr) + 0.5) * (1.0f / (float)(ctx->rb.sizey)); // calculate row of pixel - dmin = 2.0f; // reset min distance to edge pixel for (a = 0; a < num_feather_verts; a++) { // loop through all outer edge buffer pixels @@ -645,9 +638,6 @@ int rast_scan_feather(struct r_fill_context *ctx, /* set intensity, do the += so overlapping gradients are additive */ *cpxl = (idist / (idist + odist)); -/* - * End modified code from double edge mask node - */ } } } From 6aeb3ddb20e607387d6f52db48c8327930d3b6d9 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Thu, 31 May 2012 21:56:41 +0000 Subject: [PATCH 146/183] small code refactor to remove redundant calculations --- intern/raskter/raskter.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index e30df66648b..e565348cc79 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -464,8 +464,8 @@ int rast_scan_feather(struct r_fill_context *ctx, float idist; // idist = current inner edge distance float dx; // dx = X-delta (used for distance proportion calculation) float dy; // dy = Y-delta (used for distance proportion calculation) - float xpxw; - float ypxh; + float xpxw = (1.0f / (float)(ctx->rb.sizex)); // xpxw = normalized pixel width + float ypxh = (1.0f / (float)(ctx->rb.sizey)); // ypxh = normalized pixel height /* * If the number of verts specified to render as a polygon is less than 3, @@ -588,8 +588,6 @@ int rast_scan_feather(struct r_fill_context *ctx, mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { - xpxw = (1.0f / (float)(ctx->rb.sizex)); - ypxh = (1.0f / (float)(ctx->rb.sizey)); t = ((float)((cpxl - spxl) % ctx->rb.sizex) + 0.5f) * xpxw; fsz = ((float)(y_curr) + 0.5f) * ypxh; /* draw the pixels. */ From 7f6dd1861d5f97375ae23d72dbd13d493ff97a2a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 Jun 2012 05:46:09 +0000 Subject: [PATCH 147/183] style cleanup --- intern/raskter/raskter.c | 9 ++-- source/blender/blenkernel/intern/mask.c | 63 +++++++++++++------------ source/blender/editors/mask/mask_ops.c | 2 +- 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index e565348cc79..2e57ef746c3 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -305,12 +305,13 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ e_curr = e_curr->e_next; mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; - if((y_curr >= 0) && (y_curr < ctx->rb.sizey)){ + if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { /* draw the pixels. */ - for (; cpxl <= mpxl; cpxl++){ - if(*cpxl < 0.5f){ + for (; cpxl <= mpxl; cpxl++) { + if (*cpxl < 0.5f) { *cpxl = 1.0f; - }else{ + } + else { *cpxl = 0.0f; } } diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index e6f328546f5..c510dce12ec 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -223,7 +223,7 @@ float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point, i MaskSplinePoint *point, *prev; float (*diff_points)[2], (*fp)[2]; int a, len, resol; - if(!dynamic_res){ + if (!dynamic_res) { max_dseg_len = 0.01f; } resol = BKE_mask_spline_resolution(spline, max_dseg_len); @@ -284,13 +284,13 @@ float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point, i return diff_points; } -float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point, int dynamic_res, float max_dseg_len))[2] +float (*BKE_mask_spline_feather_differentiated_points(MaskSpline * spline, int *tot_feather_point, int dynamic_res, float max_dseg_len))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); float (*feather)[2], (*fp)[2]; int i, j, tot, resol; - if(!dynamic_res){ + if (!dynamic_res) { max_dseg_len = 0.005f; } resol = BKE_mask_spline_feather_resolution(spline, max_dseg_len); @@ -320,7 +320,7 @@ float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *t return feather; } -float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] +float (*BKE_mask_spline_feather_points(MaskSpline * spline, int *tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -1085,8 +1085,8 @@ void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplineP MaskSplinePoint *prev_point, *next_point; const char h_back[2] = {point->bezt.h1, point->bezt.h2}; const float length_average = (do_recalc_length) ? 0.0f /* dummy value */ : - (len_v3v3(point->bezt.vec[0], point->bezt.vec[1]) + - len_v3v3(point->bezt.vec[1], point->bezt.vec[2])) / 2.0f; + (len_v3v3(point->bezt.vec[0], point->bezt.vec[1]) + + len_v3v3(point->bezt.vec[1], point->bezt.vec[2])) / 2.0f; BKE_mask_get_handle_point_adjacent(mask, spline, point, &prev_point, &next_point); @@ -1142,11 +1142,11 @@ void BKE_mask_update_deform(Mask *mask) const int i_next = (i + 1) % spline->tot_point; BezTriple *bezt_prev = &spline->points[i_prev].bezt; - BezTriple *bezt = &spline->points[i ].bezt; + BezTriple *bezt = &spline->points[i].bezt; BezTriple *bezt_next = &spline->points[i_next].bezt; BezTriple *bezt_def_prev = &spline->points_deform[i_prev].bezt; - BezTriple *bezt_def = &spline->points_deform[i ].bezt; + BezTriple *bezt_def = &spline->points_deform[i].bezt; BezTriple *bezt_def_next = &spline->points_deform[i_next].bezt; float w_src[4]; @@ -1203,7 +1203,7 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) int found; if ((found = BKE_mask_layer_shape_find_frame_range(masklay, (int)ctime, - &masklay_shape_a, &masklay_shape_b))) + &masklay_shape_a, &masklay_shape_b))) { if (found == 1) { #if 0 @@ -1220,7 +1220,7 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) masklay_shape_a->frame, masklay_shape_b->frame); #endif BKE_mask_layer_shape_to_mask_interp(masklay, masklay_shape_a, masklay_shape_b, - (ctime - masklay_shape_a->frame) / w); + (ctime - masklay_shape_a->frame) / w); } else { /* always fail, should never happen */ @@ -1410,9 +1410,9 @@ BLI_INLINE void interp_v2_v2v2_flfl(float target[2], const float a[2], const flo /* linear interpolation only */ void BKE_mask_layer_shape_to_mask_interp(MaskLayer *masklay, - MaskLayerShape *masklay_shape_a, - MaskLayerShape *masklay_shape_b, - const float fac) + MaskLayerShape *masklay_shape_a, + MaskLayerShape *masklay_shape_b, + const float fac) { int tot = BKE_mask_layer_shape_totvert(masklay); if (masklay_shape_a->tot_vert == tot && masklay_shape_b->tot_vert == tot) { @@ -1462,8 +1462,8 @@ MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, int frame) /* when returning 2 - the frame isnt found but before/after frames are */ int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, int frame, - MaskLayerShape **r_masklay_shape_a, - MaskLayerShape **r_masklay_shape_b) + MaskLayerShape **r_masklay_shape_a, + MaskLayerShape **r_masklay_shape_b) { MaskLayerShape *masklay_shape; @@ -1516,16 +1516,16 @@ MaskLayerShape *BKE_mask_layer_shape_varify_frame(MaskLayer *masklay, int frame) } #if 0 + { + MaskLayerShape *masklay_shape; + int i = 0; + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) { - MaskLayerShape *masklay_shape; - int i = 0; - for (masklay_shape = masklay->splines_shapes.first; - masklay_shape; - masklay_shape = masklay_shape->next) - { - printf("mask %d, %d\n", i++, masklay_shape->frame); - } + printf("mask %d, %d\n", i++, masklay_shape->frame); } + } #endif return masklay_shape; @@ -1554,7 +1554,7 @@ void BKE_mask_layer_shape_sort(MaskLayer *masklay) } int BKE_mask_layer_shape_spline_from_index(MaskLayer *masklay, int index, - MaskSpline **r_masklay_shape, int *r_index) + MaskSpline **r_masklay_shape, int *r_index) { MaskSpline *spline; @@ -1609,16 +1609,16 @@ static void interp_weights_uv_v2_apply(const float uv[2], float r_pt[2], const f /* when a now points added - resize all shapekey array */ void BKE_mask_layer_shape_changed_add(MaskLayer *masklay, int index, - int do_init, int do_init_interpolate) + int do_init, int do_init_interpolate) { MaskLayerShape *masklay_shape; /* spline index from masklay */ MaskSpline *spline; - int spline_point_index; + int spline_point_index; if (BKE_mask_layer_shape_spline_from_index(masklay, index, - &spline, &spline_point_index)) + &spline, &spline_point_index)) { /* sanity check */ /* the point has already been removed in this array so subtract one when comparing with the shapes */ @@ -1767,7 +1767,7 @@ static void linear_clamp_vn_vn(float *array, const int size) while (i--) { if (*arr <= 0.0f) *arr = 0.0f; else if (*arr >= 1.0f) *arr = 1.0f; - else *arr = srgb_to_linearrgb(*arr); + else *arr = srgb_to_linearrgb(*arr); arr--; } } @@ -1782,9 +1782,10 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) float *buffer_tmp = MEM_mallocN(sizeof(float) * buffer_size, __func__); float max_dseg_len = 0.0f; - if(width >= height){ + if (width >= height) { max_dseg_len = (float)(width); - }else{ + } + else { max_dseg_len = (float)(height); } max_dseg_len = 1.0f / max_dseg_len; @@ -1807,7 +1808,7 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) int tot_diff_feather_points; diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point, 1, max_dseg_len); - if(tot_diff_point){ + if (tot_diff_point) { diff_feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_diff_feather_points, 1, max_dseg_len); } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index e56eb181a51..4c96e70e710 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1088,7 +1088,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const MASKPOINT_DESEL_ALL(point); if ((spline->flag & MASK_SPLINE_CYCLIC) || - (point_index > 0 && point_index != spline->tot_point - 1)) + (point_index > 0 && point_index != spline->tot_point - 1)) { BKE_mask_calc_tangent_polyline(mask, spline, point, tangent_point); sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]); From 70df1956a9fc3a661264b9b9fecfa30631fd6b67 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 1 Jun 2012 11:44:46 +0000 Subject: [PATCH 148/183] Small refactor of mask sliding operator Also aspect ratio correction is not needed for BKE_mask_point_set_handle --- source/blender/blenkernel/BKE_mask.h | 2 +- source/blender/blenkernel/intern/mask.c | 17 ++-------- source/blender/editors/mask/mask_ops.c | 33 +++++++++---------- .../editors/transform/transform_conversions.c | 2 +- 4 files changed, 20 insertions(+), 34 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 8fc979e941b..347469ad92d 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -66,7 +66,7 @@ float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feath int BKE_mask_point_has_handle(struct MaskSplinePoint *point); void BKE_mask_point_handle(struct MaskSplinePoint *point, float handle[2]); void BKE_mask_point_set_handle(struct MaskSplinePoint *point, float loc[2], int keep_direction, - float aspx, float aspy, float orig_handle[2], float orig_vec[3][3]); + float orig_handle[2], float orig_vec[3][3]); float *BKE_mask_point_segment_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, int *tot_diff_point); float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, int *tot_feather_point); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index c510dce12ec..3b7e69c9f29 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -386,7 +386,7 @@ void BKE_mask_point_handle(MaskSplinePoint *point, float handle[2]) handle[1] = (point->bezt.vec[1][1] - vec[0]); } -void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_direction, float aspx, float aspy, +void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_direction, float orig_handle[2], float orig_vec[3][3]) { BezTriple *bezt = &point->bezt; @@ -396,11 +396,6 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di sub_v2_v2v2(v1, loc, orig_vec[1]); sub_v2_v2v2(v2, orig_handle, orig_vec[1]); - v1[0] *= aspx; - v1[1] *= aspy; - v2[0] *= aspx; - v2[1] *= aspx; - project_v2_v2v2(vec, v1, v2); if (dot_v2v2(v2, vec) > 0) { @@ -408,14 +403,8 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di sub_v2_v2v2(v1, orig_vec[0], orig_vec[1]); - v1[0] *= aspx; - v1[1] *= aspy; - mul_v2_fl(v1, len / len_v2(v1)); - v1[0] /= aspx; - v1[1] /= aspy; - add_v2_v2v2(bezt->vec[0], bezt->vec[1], v1); sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v1); } @@ -427,8 +416,8 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di else { sub_v2_v2v2(v1, loc, bezt->vec[1]); - v2[0] = -v1[1] * aspy / aspx; - v2[1] = v1[0] * aspx / aspy; + v2[0] = -v1[1]; + v2[1] = v1[0]; add_v2_v2v2(bezt->vec[0], bezt->vec[1], v2); sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v2); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 4c96e70e710..0da761940eb 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -551,7 +551,6 @@ typedef struct SlidePointData { MaskSplinePoint *point; MaskSplinePointUW *uw; float handle[2], no[2], feather[2]; - float aspx, aspy; int width, height; float weight; @@ -609,8 +608,6 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) customdata->action = action; customdata->uw = uw; - ED_mask_aspect(C, &customdata->aspx, &customdata->aspy); - if (uw) { float co[2]; @@ -732,7 +729,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) add_v2_v2(offco, data->co); add_v2_v2(offco, delta); - BKE_mask_point_set_handle(data->point, offco, data->curvature_only, data->aspx, data->aspy, data->handle, data->vec); + BKE_mask_point_set_handle(data->point, offco, data->curvature_only, data->handle, data->vec); } else if (data->action == SLIDE_ACTION_POINT) { float delta[2]; @@ -747,20 +744,21 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) } else if (data->action == SLIDE_ACTION_FEATHER) { float vec[2], no[2], p[2], c[2], w, offco[2]; - float *weight; + float *weight = NULL; add_v2_v2v2(offco, data->feather, dco); if (data->uw) { float u = projection_on_spline(data->spline, data->point, data->uw->u, offco); - if (u > 0.0f && u < 1.0f) + if (u > 0.0f && u < 1.0f) { data->uw->u = u; - data->uw = BKE_mask_point_sort_uw(data->point, data->uw); - weight = &data->uw->w; - BKE_mask_point_normal(data->spline, data->point, data->uw->u, no); - BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p); + data->uw = BKE_mask_point_sort_uw(data->point, data->uw); + weight = &data->uw->w; + BKE_mask_point_normal(data->spline, data->point, data->uw->u, no); + BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p); + } } else { weight = &bezt->weight; @@ -768,18 +766,17 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) copy_v2_v2(p, bezt->vec[1]); } - sub_v2_v2v2(c, offco, p); - project_v2_v2v2(vec, c, no); + if (weight) { + sub_v2_v2v2(c, offco, p); + project_v2_v2v2(vec, c, no); - vec[0] *= data->aspx; - vec[1] *= data->aspy; + w = len_v2(vec); - w = len_v2(vec); + if (dot_v2v2(no, vec) <= 0.0f) + w = 0.0f; - if (dot_v2v2(no, vec) > 0.0f) *weight = w; - else - *weight = 0; + } } WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 23a88e6e547..8a7caeb3060 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -6071,7 +6071,7 @@ void flushTransMasking(TransInfo *t) td->loc2d[1]= td->loc[1]*invy; if (tdm->is_handle) - BKE_mask_point_set_handle(tdm->point, td->loc2d, t->flag & T_ALT_TRANSFORM, aspx, aspy, tdm->orig_handle, tdm->vec); + BKE_mask_point_set_handle(tdm->point, td->loc2d, t->flag & T_ALT_TRANSFORM, tdm->orig_handle, tdm->vec); } } From ecac5aef754e42877e560aa36a7f0a9139c7bf36 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 1 Jun 2012 11:44:52 +0000 Subject: [PATCH 149/183] Changes to mask point slide operator: - Original slide would create overall feather for spline - Sliding of feather points for already defined feather would control individual feather points weight - Sliding of feather points with Ctrl hold down would switch to overall feather control --- source/blender/blenkernel/BKE_mask.h | 1 + source/blender/blenkernel/intern/mask.c | 20 ++++ source/blender/editors/mask/mask_ops.c | 122 ++++++++++++++++++++++-- 3 files changed, 133 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 347469ad92d..03c0b45f84c 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -50,6 +50,7 @@ void BKE_mask_layer_remove(struct Mask *mask, struct MaskLayer *masklay); void BKE_mask_layer_free(struct MaskLayer *masklay); void BKE_mask_spline_free(struct MaskSpline *spline); +struct MaskSpline *BKE_mask_spline_copy(struct MaskSpline *spline); void BKE_mask_point_free(struct MaskSplinePoint *point); void BKE_mask_layer_unique_name(struct Mask *mask, struct MaskLayer *masklay); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 3b7e69c9f29..31da0dae1b3 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -736,6 +736,26 @@ void BKE_mask_spline_free(MaskSpline *spline) MEM_freeN(spline); } +MaskSpline *BKE_mask_spline_copy(MaskSpline *spline) +{ + MaskSpline *nspline = MEM_callocN(sizeof(MaskSpline), "new spline"); + int i; + + *nspline = *spline; + + nspline->points_deform = NULL; + nspline->points = MEM_dupallocN(nspline->points); + + for (i = 0; i < nspline->tot_point; i++) { + MaskSplinePoint *point = &nspline->points[i]; + + if (point->uw) + point->uw = MEM_dupallocN(point->uw); + } + + return nspline; +} + void BKE_mask_layer_shape_free(MaskLayerShape *masklay_shape) { MEM_freeN(masklay_shape->data); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 0da761940eb..f35d58219e2 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -547,7 +547,7 @@ typedef struct SlidePointData { Mask *mask; MaskLayer *masklay; - MaskSpline *spline; + MaskSpline *spline, *orig_spline; MaskSplinePoint *point; MaskSplinePointUW *uw; float handle[2], no[2], feather[2]; @@ -555,8 +555,29 @@ typedef struct SlidePointData { float weight; short curvature_only, accurate; + short initial_feather, overall_feather; } SlidePointData; +static int slide_point_check_initial_feather(MaskSpline *spline) +{ + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + int j; + + if (point->bezt.weight != 0.0f) + return FALSE; + + for (j = 0; j < point->tot_uw; j++) { + if (point->uw[j].w != 0.0f) + return FALSE; + } + } + + return TRUE; +} + static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) { Mask *mask = CTX_data_edit_mask(C); @@ -622,12 +643,18 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) } else { BezTriple *bezt = &point->bezt; + BKE_mask_point_normal(spline, point, 0.0f, customdata->no); customdata->feather[0] = bezt->vec[1][0] + customdata->no[0] * bezt->weight; customdata->feather[1] = bezt->vec[1][1] + customdata->no[1] * bezt->weight; + + customdata->weight = bezt->weight; } + if (customdata->action == SLIDE_ACTION_FEATHER) + customdata->initial_feather = slide_point_check_initial_feather(spline); + copy_m3_m3(customdata->vec, point->bezt.vec); if (BKE_mask_point_has_handle(point)) BKE_mask_point_handle(point, customdata->handle); @@ -676,22 +703,68 @@ static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_PASS_THROUGH; } +static void slide_point_delta_all_feather(SlidePointData *data, float delta) +{ + int i; + + for (i = 0; i < data->spline->tot_point; i++) { + MaskSplinePoint *point = &data->spline->points[i]; + MaskSplinePoint *orig_point = &data->orig_spline->points[i]; + int j; + + point->bezt.weight = orig_point->bezt.weight + delta; + if (point->bezt.weight < 0.0f) + point->bezt.weight = 0.0f; + + for (j = 0; j < point->tot_uw; j++) { + point->uw[j].w = orig_point->uw[j].w + delta; + if (point->uw[j].w < 0.0f) + point->uw[j].w = 0.0f; + } + } +} + +static void slide_point_restore_spline(SlidePointData *data) +{ + int i; + + for (i = 0; i < data->spline->tot_point; i++) { + MaskSplinePoint *point = &data->spline->points[i]; + MaskSplinePoint *orig_point = &data->orig_spline->points[i]; + int j; + + point->bezt = orig_point->bezt; + + for (j = 0; j < point->tot_uw; j++) + point->uw[j] = orig_point->uw[j]; + } +} + static void cancel_slide_point(SlidePointData *data) { /* cancel sliding */ - if (data->action == SLIDE_ACTION_FEATHER) { - if (data->uw) - data->uw->w = data->weight; - else - data->point->bezt.weight = data->weight; + + if (data->orig_spline) { + slide_point_restore_spline(data); } else { - copy_m3_m3(data->point->bezt.vec, data->vec); + if (data->action == SLIDE_ACTION_FEATHER) { + if (data->uw) + data->uw->w = data->weight; + else + data->point->bezt.weight = data->weight; + } + else { + copy_m3_m3(data->point->bezt.vec, data->vec); + } } } static void free_slide_point_data(SlidePointData *data) { + if (data->orig_spline) + BKE_mask_spline_free(data->orig_spline); + MEM_freeN(data); } @@ -706,8 +779,12 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) case RIGHTCTRLKEY: case LEFTSHIFTKEY: case RIGHTSHIFTKEY: - if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) - data->curvature_only = event->val == KM_PRESS; + if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) { + if (data->action == SLIDE_ACTION_FEATHER) + data->overall_feather = event->val == KM_PRESS; + else + data->curvature_only = event->val == KM_PRESS; + } if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) data->accurate = event->val == KM_PRESS; @@ -745,6 +822,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) else if (data->action == SLIDE_ACTION_FEATHER) { float vec[2], no[2], p[2], c[2], w, offco[2]; float *weight = NULL; + int overall_feather = data->overall_feather || data->initial_feather; add_v2_v2v2(offco, data->feather, dco); @@ -775,7 +853,31 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) if (dot_v2v2(no, vec) <= 0.0f) w = 0.0f; - *weight = w; + if (overall_feather) { + float delta = w - data->weight; + + if (data->orig_spline == NULL) { + /* restore weight for currently sliding point, so orig_spline would be created + * with original weights used + */ + *weight = data->weight; + + data->orig_spline = BKE_mask_spline_copy(data->spline); + } + + slide_point_delta_all_feather(data, delta); + } + else { + if (data->orig_spline) { + /* restore possible overall feather changes */ + slide_point_restore_spline(data); + + BKE_mask_spline_free(data->orig_spline); + data->orig_spline = NULL; + } + + *weight = w; + } } } From 1450bc244fbaeb518d8826b216bd1b4b47bef2af Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 1 Jun 2012 12:25:18 +0000 Subject: [PATCH 150/183] Cleanup in spline diffirintiation code - encapsulate max segment length to resolution calculation functions rather than doing this from callee. Also switch mask drawing code do the same spline resolution calculation as used for compositor (which takes frame dimensions into account). --- source/blender/blenkernel/BKE_mask.h | 19 +++++-- source/blender/blenkernel/intern/mask.c | 69 ++++++++++++++++--------- source/blender/editors/mask/mask_draw.c | 23 ++++++--- source/blender/editors/mask/mask_ops.c | 6 ++- 4 files changed, 81 insertions(+), 36 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 03c0b45f84c..1eb130f1713 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -57,10 +57,14 @@ void BKE_mask_layer_unique_name(struct Mask *mask, struct MaskLayer *masklay); /* splines */ struct MaskSpline *BKE_mask_spline_add(struct MaskLayer *masklay); -int BKE_mask_spline_resolution(struct MaskSpline *spline, float max_seg_len); -float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point, int dynamic_res, float max_dseg_len))[2]; -float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point, int dynamic_res, float max_dseg_len))[2]; +float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point))[2]; +float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point))[2]; + +float (*BKE_mask_spline_differentiate_with_resolution(struct MaskSpline *spline, int width, int height, int *tot_diff_point))[2]; +float (*BKE_mask_spline_feather_differentiated_points_with_resolution(struct MaskSpline *spline, + int width, int height, int *tot_feather_point))[2]; + float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2]; /* point */ @@ -68,9 +72,18 @@ int BKE_mask_point_has_handle(struct MaskSplinePoint *point); void BKE_mask_point_handle(struct MaskSplinePoint *point, float handle[2]); void BKE_mask_point_set_handle(struct MaskSplinePoint *point, float loc[2], int keep_direction, float orig_handle[2], float orig_vec[3][3]); + float *BKE_mask_point_segment_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, int *tot_diff_point); float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, int *tot_feather_point); + +float *BKE_mask_point_segment_diff_with_resolution(struct MaskSpline *spline, struct MaskSplinePoint *point, + int width, int height, int *tot_diff_point); + +float *BKE_mask_point_segment_feather_diff_with_resolution(struct MaskSpline *spline, struct MaskSplinePoint *point, + int width, int height, + int *tot_feather_point); + void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2]); void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float n[2]); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 31da0dae1b3..6b57b22311d 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -149,11 +149,18 @@ MaskSpline *BKE_mask_spline_add(MaskLayer *masklay) return spline; } -int BKE_mask_spline_resolution(MaskSpline *spline, float max_seg_len) +static int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) { - const float max_segment = max_seg_len; + float max_segment = 0.01f; int i, resol = 1; + if (width != 0 && height != 0) { + if (width >= height) + max_segment = 1.0f / (float) width; + else + max_segment = 1.0f / (float) height; + } + for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; MaskSplinePoint *next_point; @@ -186,10 +193,10 @@ int BKE_mask_spline_resolution(MaskSpline *spline, float max_seg_len) return resol; } -int BKE_mask_spline_feather_resolution(MaskSpline *spline, float max_seg_len) +static int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height) { const float max_segment = 0.005; - int resol = BKE_mask_spline_resolution(spline, max_seg_len); + int resol = BKE_mask_spline_resolution(spline, width, height); float max_jump = 0.0f; int i; @@ -216,18 +223,13 @@ int BKE_mask_spline_feather_resolution(MaskSpline *spline, float max_seg_len) return resol; } -float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point, int dynamic_res, float max_dseg_len))[2] +float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height, int *tot_diff_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); MaskSplinePoint *point, *prev; float (*diff_points)[2], (*fp)[2]; - int a, len, resol; - if (!dynamic_res) { - max_dseg_len = 0.01f; - } - resol = BKE_mask_spline_resolution(spline, max_dseg_len); - + int a, len, resol = BKE_mask_spline_resolution(spline, width, height); if (spline->tot_point <= 1) { /* nothing to differentiate */ @@ -284,16 +286,18 @@ float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point, i return diff_points; } -float (*BKE_mask_spline_feather_differentiated_points(MaskSpline * spline, int *tot_feather_point, int dynamic_res, float max_dseg_len))[2] +float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2] +{ + return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point); +} + +float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height, + int *tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); float (*feather)[2], (*fp)[2]; - int i, j, tot, resol; - if (!dynamic_res) { - max_dseg_len = 0.005f; - } - resol = BKE_mask_spline_feather_resolution(spline, max_dseg_len); + int i, j, tot, resol = BKE_mask_spline_feather_resolution(spline, width, height); tot = resol * spline->tot_point; feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather diff points"); @@ -320,6 +324,11 @@ float (*BKE_mask_spline_feather_differentiated_points(MaskSpline * spline, int * return feather; } +float (*BKE_mask_spline_feather_differentiated_points(MaskSpline * spline, int *tot_feather_point))[2] +{ + return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point); +} + float (*BKE_mask_spline_feather_points(MaskSpline * spline, int *tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -424,10 +433,12 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di } } -float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_feather_point) +float *BKE_mask_point_segment_feather_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, + int width, int height, + int *tot_feather_point) { float *feather, *fp; - int i, resol = BKE_mask_spline_feather_resolution(spline, 0.005f); + int i, resol = BKE_mask_spline_feather_resolution(spline, width, height); feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); @@ -448,13 +459,18 @@ float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint * return feather; } -float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_diff_point) +float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_feather_point) +{ + return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point); +} + +float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, int width, int height, int *tot_diff_point) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); BezTriple *bezt, *next; float *diff_points, *fp; - int j, resol = BKE_mask_spline_resolution(spline, 0.01f); + int j, resol = BKE_mask_spline_resolution(spline, width, height); bezt = &point->bezt; @@ -484,6 +500,11 @@ float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, i return diff_points; } +float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_diff_point) +{ + return BKE_mask_point_segment_diff_with_resolution(spline, point, 0, 0, tot_diff_point); +} + void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float u, float co[2]) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); @@ -1816,9 +1837,11 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) float (*diff_feather_points)[2]; int tot_diff_feather_points; - diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point, 1, max_dseg_len); + diff_points = BKE_mask_spline_differentiate_with_resolution(spline, width, height, &tot_diff_point); if (tot_diff_point) { - diff_feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_diff_feather_points, 1, max_dseg_len); + diff_feather_points = + BKE_mask_spline_feather_differentiated_points_with_resolution(spline, width, height, + &tot_diff_feather_points); } /* TODO, make this optional! */ diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 5b8bf1075b4..e580088e25b 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -323,7 +323,8 @@ static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot } static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, - const char draw_flag, const char draw_type) + const char draw_flag, const char draw_type, + int width, int height) { unsigned char rgb_tmp[4]; @@ -336,7 +337,7 @@ static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, int tot_feather_point; float (*feather_points)[2]; - diff_points = BKE_mask_spline_differentiate(spline, &tot_diff_point, 0, 0.0f); + diff_points = BKE_mask_spline_differentiate_with_resolution(spline, width, height, &tot_diff_point); if (!diff_points) return; @@ -347,7 +348,7 @@ static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - feather_points = BKE_mask_spline_feather_differentiated_points(spline, &tot_feather_point, 0, 0.0f); + feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, width, height, &tot_feather_point); /* draw feather */ mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp); @@ -371,8 +372,8 @@ static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, (void)draw_type; } -static void draw_masklays(Mask *mask, - const char draw_flag, const char draw_type) +static void draw_masklays(Mask *mask, const char draw_flag, const char draw_type, + int width, int height) { MaskLayer *masklay; @@ -386,7 +387,7 @@ static void draw_masklays(Mask *mask, for (spline = masklay->splines.first; spline; spline = spline->next) { /* draw curve itself first... */ - draw_spline_curve(masklay, spline, draw_flag, draw_type); + draw_spline_curve(masklay, spline, draw_flag, draw_type, width, height); // draw_spline_parents(masklay, spline); @@ -400,7 +401,7 @@ static void draw_masklays(Mask *mask, void *back = spline->points_deform; spline->points_deform = NULL; - draw_spline_curve(masklay, spline, draw_flag, draw_type); + draw_spline_curve(masklay, spline, draw_flag, draw_type, width, height); // draw_spline_parents(masklay, spline); draw_spline_points(masklay, spline); spline->points_deform = back; @@ -413,9 +414,15 @@ void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type) { Mask *mask = CTX_data_edit_mask(C); + int width, height; if (!mask) return; - draw_masklays(mask, draw_flag, draw_type); + /* TODO: for now, in the future better to make sure all utility functions + * are using const specifier for non-changing pointers + */ + ED_mask_size((bContext *)C, &width, &height); + + draw_masklays(mask, draw_flag, draw_type, width, height); } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index f35d58219e2..410b8d10c88 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -348,14 +348,16 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c float *diff_points; int tot_diff_point; - diff_points = BKE_mask_point_segment_diff(spline, cur_point, &tot_diff_point); + diff_points = BKE_mask_point_segment_diff_with_resolution(spline, cur_point, width, height, + &tot_diff_point); if (diff_points) { int i, tot_feather_point, tot_point; float *feather_points = NULL, *points; if (feather) { - feather_points = BKE_mask_point_segment_feather_diff(spline, cur_point, + feather_points = BKE_mask_point_segment_feather_diff_with_resolution(spline, cur_point, + width, height, &tot_feather_point); points = feather_points; From 54b2d1e1ffaee4384259c1f79c27d93d0042e302 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 1 Jun 2012 12:30:27 +0000 Subject: [PATCH 151/183] Small change to mask slide operator: if current weight goes below zero, higher weights are still getting affected by weight delta. --- source/blender/editors/mask/mask_ops.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 410b8d10c88..010066f705f 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -852,11 +852,13 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) w = len_v2(vec); - if (dot_v2v2(no, vec) <= 0.0f) - w = 0.0f; - if (overall_feather) { - float delta = w - data->weight; + float delta; + + if (dot_v2v2(no, vec) <= 0.0f) + w = -w; + + delta = w - data->weight; if (data->orig_spline == NULL) { /* restore weight for currently sliding point, so orig_spline would be created @@ -870,6 +872,9 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) slide_point_delta_all_feather(data, delta); } else { + if (dot_v2v2(no, vec) <= 0.0f) + w = 0.0f; + if (data->orig_spline) { /* restore possible overall feather changes */ slide_point_restore_spline(data); From 44693e709a8afe7dcf294688b8736291646d5a3b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 1 Jun 2012 12:34:44 +0000 Subject: [PATCH 152/183] Change in debug print for BKE_mask_spline_ensure_deform -- "alloc new spline" was a bit misleading, changed with "alloc new deform spline" --- source/blender/blenkernel/intern/mask.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 6b57b22311d..a7f6459f382 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1200,7 +1200,7 @@ void BKE_mask_spline_ensure_deform(MaskSpline *spline) // printf("SPLINE ALLOC %p %d\n", spline->points_deform, (int)(MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform))); if (spline->points_deform == NULL || allocated_points != spline->tot_point) { - printf("alloc new spline\n"); + printf("alloc new deform spline\n"); if (spline->points_deform) { int i; From 851954fb49f176572bdcdf2a4b0349f979eac4dd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 1 Jun 2012 13:05:05 +0000 Subject: [PATCH 153/183] Initial expose of tools into interface for mask editing. Maybe no ideal, but looks better than completely empty panels. --- release/scripts/startup/bl_ui/space_clip.py | 162 ++++++++++++++++---- 1 file changed, 132 insertions(+), 30 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index ab1bd817490..1c94b4db95e 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -44,9 +44,12 @@ class CLIP_HT_header(Header): sub.menu("CLIP_MT_clip") - if clip and sc.mode != 'MASKEDITING': - sub.menu("CLIP_MT_track") - sub.menu("CLIP_MT_reconstruction") + if clip: + if sc.mode == 'MASKEDITING': + sub.menu("CLIP_MT_mask") + else: + sub.menu("CLIP_MT_track") + sub.menu("CLIP_MT_reconstruction") if sc.mode != 'MASKEDITING': layout.prop(sc, "view", text="", expand=True) @@ -55,6 +58,14 @@ class CLIP_HT_header(Header): if sc.view == 'CLIP': layout.prop(sc, "mode", text="") layout.prop(sc, "pivot_point", text="", icon_only=True) + + if sc.mode == 'MASKEDITING': + toolsettings = context.tool_settings + + row = layout.row(align=True) + row.prop(toolsettings, "use_proportional_edit_mask", text="", icon_only=True) + if toolsettings.use_proportional_edit_objects: + row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True) elif sc.view == 'GRAPH': row = layout.row(align=True) @@ -75,15 +86,8 @@ class CLIP_HT_header(Header): row.template_ID(sc, "clip", open='clip.open') if sc.mode == 'MASKEDITING': - toolsettings = context.tool_settings - row = layout.row() row.template_ID(sc, "mask", new="mask.new") - - row = layout.row(align=True) - row.prop(toolsettings, "use_proportional_edit_mask", text="", icon_only=True) - if toolsettings.use_proportional_edit_objects: - row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True) if clip: tracking = clip.tracking @@ -116,6 +120,16 @@ class CLIP_PT_clip_view_panel: return clip and sc.view == 'CLIP' +class CLIP_PT_mask_view_panel: + + @classmethod + def poll(cls, context): + sc = context.space_data + clip = sc.clip + + return clip and sc.view == 'CLIP' and sc.mode == 'MASKEDITING' + + class CLIP_PT_tracking_panel: @classmethod @@ -136,16 +150,6 @@ class CLIP_PT_reconstruction_panel: return clip and sc.mode == 'RECONSTRUCTION' and sc.view == 'CLIP' -class CLIP_PT_distortion_panel: - - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return clip and sc.mode == 'DISTORTION' and sc.view == 'CLIP' - - class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' @@ -372,11 +376,51 @@ class CLIP_PT_tools_object(CLIP_PT_reconstruction_panel, Panel): col.prop(settings, "object_distance") -class CLIP_PT_tools_grease_pencil(CLIP_PT_distortion_panel, Panel): +class CLIP_PT_tools_mask(CLIP_PT_mask_view_panel, Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'TOOLS' + bl_label = "Mask Tools" + + def draw(self, context): + layout = self.layout + + col = layout.column(align=True) + col.label(text="Transform:") + col.operator("transform.translate") + col.operator("transform.rotate") + col.operator("transform.resize", text="Scale") + + col = layout.column(align=True) + col.label(text="Spline:") + col.operator("mask.delete") + col.operator("mask.cyclic_toggle") + + col = layout.column(align=True) + col.label(text="Parenting:") + col.operator("mask.parent_set") + col.operator("mask.parent_clear") + + +class CLIP_PT_tools_grease_pencil(Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Grease Pencil" + @classmethod + def poll(cls, context): + sc = context.space_data + clip = sc.clip + + if not clip: + return False + + if sc.mode == 'DISTORTION': + return sc.view == 'CLIP' + elif sc.mode == 'MASKEDITING': + return True + + return False + def draw(self, context): layout = self.layout @@ -591,7 +635,7 @@ class CLIP_PT_mask_objects(Panel): active = mask.layers.active if active: layout.prop(active, "name") - + # blending row = layout.row(align=True) row.prop(active, "alpha") @@ -718,12 +762,11 @@ class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): col.label(text="Display Aspect Ratio:") row = col.row() row.prop(clip, "display_aspect", text="") - + if sc.mode == 'MASKEDITING': col = layout.column() col.prop(sc, "mask_draw_type", text="") col.prop(sc, "show_mask_smooth") - class CLIP_PT_marker_display(CLIP_PT_clip_view_panel, Panel): @@ -900,6 +943,7 @@ class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel): layout.operator("clip.open", icon='FILESEL') + class CLIP_PT_tools_clip(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' @@ -1079,16 +1123,26 @@ class CLIP_MT_select(Menu): def draw(self, context): layout = self.layout + sc = context.space_data - layout.operator("clip.select_border") - layout.operator("clip.select_circle") + if sc.mode == 'MASKEDITING': + layout.operator("mask.select_border") + layout.operator("mask.select_circle") - layout.separator() + layout.separator() - layout.operator("clip.select_all").action = 'TOGGLE' - layout.operator("clip.select_all", text="Inverse").action = 'INVERT' + layout.operator("mask.select_all").action = 'TOGGLE' + layout.operator("mask.select_all", text="Inverse").action = 'INVERT' + else: + layout.operator("clip.select_border") + layout.operator("clip.select_circle") - layout.menu("CLIP_MT_select_grouped") + layout.separator() + + layout.operator("clip.select_all").action = 'TOGGLE' + layout.operator("clip.select_all", text="Inverse").action = 'INVERT' + + layout.menu("CLIP_MT_select_grouped") class CLIP_MT_select_grouped(Menu): @@ -1132,6 +1186,54 @@ class CLIP_MT_tracking_specials(Menu): props.action = 'UNLOCK' +class CLIP_MT_mask(Menu): + bl_label = "Mask" + + def draw(self, context): + layout = self.layout + + layout.operator("mask.delete") + + layout.separator() + layout.operator("mask.cyclic_toggle") + + layout.separator() + layout.operator("mask.parent_clear") + layout.operator("mask.parent_set") + + layout.separator() + layout.operator("mask.shape_key_clear") + layout.operator("mask.shape_key_insert") + + layout.separator() + layout.menu("CLIP_MT_mask_visibility") + layout.menu("CLIP_MT_mask_transform") + + +class CLIP_MT_mask_visibility(Menu): + bl_label = "Show/Hide" + + def draw(self, context): + layout = self.layout + + layout.operator("mask.hide_view_clear", text="Show Hidden") + layout.operator("mask.hide_view_set", text="Hide Selected") + + props = layout.operator("mask.hide_view_set", text="Hide Unselected") + props.unselected = True + + +class CLIP_MT_mask_transform(Menu): + bl_label = "Transform" + + def draw(self, context): + layout = self.layout + + layout.operator("transform.translate") + layout.operator("transform.rotate") + layout.operator("transform.resize") + + class CLIP_MT_camera_presets(Menu): """Predefined tracking camera intrinsics""" bl_label = "Camera Presets" From 7f0be018bf7da43cd7c0205513d60481ff8a8905 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 1 Jun 2012 13:46:38 +0000 Subject: [PATCH 154/183] Style cleanup of own recent changes --- source/blender/blenkernel/intern/mask.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index a7f6459f382..407216f5578 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -223,7 +223,8 @@ static int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int return resol; } -float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height, int *tot_diff_point))[2] +float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height, + int *tot_diff_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -464,7 +465,8 @@ float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint * return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point); } -float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, int width, int height, int *tot_diff_point) +float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, + int width, int height, int *tot_diff_point) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); @@ -1197,7 +1199,7 @@ void BKE_mask_update_deform(Mask *mask) void BKE_mask_spline_ensure_deform(MaskSpline *spline) { int allocated_points = (MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform)); -// printf("SPLINE ALLOC %p %d\n", spline->points_deform, (int)(MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform))); + // printf("SPLINE ALLOC %p %d\n", spline->points_deform, allocated_points); if (spline->points_deform == NULL || allocated_points != spline->tot_point) { printf("alloc new deform spline\n"); From 1691414d44402c2730334a215c11e64351873967 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Fri, 1 Jun 2012 13:49:49 +0000 Subject: [PATCH 155/183] re-remove XOR style writes from inner loop of rasterizer. is pointless and less flexible after blending was added at higher level. --- intern/raskter/raskter.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 2e57ef746c3..279b1226e5f 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -308,12 +308,7 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { /* draw the pixels. */ for (; cpxl <= mpxl; cpxl++) { - if (*cpxl < 0.5f) { - *cpxl = 1.0f; - } - else { - *cpxl = 0.0f; - } + *cpxl = 1.0f; } } } From 341a99189e661e1894e02d3e03698aa66939c3db Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 1 Jun 2012 14:42:55 +0000 Subject: [PATCH 156/183] Ignore track's disabled channels when requesting for pattern used in keying screen node --- source/blender/blenkernel/BKE_tracking.h | 2 ++ source/blender/blenkernel/intern/tracking.c | 30 ++++++++++++++----- .../operations/COM_KeyingScreenOperation.cpp | 2 +- .../nodes/node_composite_keyingscreen.c | 2 +- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 40a023101ba..e2f17a1dd18 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -74,6 +74,8 @@ void BKE_tracking_free(struct MovieTracking *tracking); struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int margin, int anchored, float pos[2], int origin[2]); +struct ImBuf *BKE_tracking_get_pattern_color_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, + struct MovieTrackingMarker *marker, int anchored); struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker); struct ImBuf *BKE_tracking_track_mask_get(struct MovieTracking *tracking, struct MovieTrackingTrack *track, diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index c51601202ff..8f181311a6f 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1177,7 +1177,8 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g } static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2]) + float min[2], float max[2], int margin, int anchored, + int grayscale, float pos[2], int origin[2]) { ImBuf *tmpibuf; int x, y; @@ -1223,12 +1224,14 @@ static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTracki origin[1] = y1 - margin; } - if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || - (track->flag & TRACK_DISABLE_RED) || - (track->flag & TRACK_DISABLE_GREEN) || - (track->flag & TRACK_DISABLE_BLUE)) - { - disable_imbuf_channels(tmpibuf, track, TRUE /* grayscale */); + if (grayscale) { + if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || + (track->flag & TRACK_DISABLE_RED) || + (track->flag & TRACK_DISABLE_GREEN) || + (track->flag & TRACK_DISABLE_BLUE)) + { + disable_imbuf_channels(tmpibuf, track, TRUE /* grayscale */); + } } return tmpibuf; @@ -1244,7 +1247,18 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo */ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, margin, anchored, pos, origin); + return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, margin, anchored, TRUE, pos, origin); +} + +ImBuf *BKE_tracking_get_pattern_color_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, + MovieTrackingMarker *marker, int anchored) +{ + float pat_min[2], pat_max[2]; + + /* see comment above */ + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, 0, anchored, FALSE, NULL, NULL); } ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker) diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index f9c9216b75a..4f6abdcbc22 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -116,7 +116,7 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri while (track) { VoronoiSite *site = &sites[i]; MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenumber); - ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, 0, TRUE, NULL, NULL); + ImBuf *pattern_ibuf = BKE_tracking_get_pattern_color_imbuf(ibuf, track, marker, TRUE); int j; zero_v3(site->color); diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c index 5cbaf4ae2ba..b7ce621a9e1 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c +++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c @@ -91,7 +91,7 @@ static void compute_gradient_screen(RenderData *rd, NodeKeyingScreenData *keying while (track) { VoronoiSite *site = &sites[i]; MovieTrackingMarker *marker = BKE_tracking_get_marker(track, rd->cfra); - ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, 0, FALSE, NULL, NULL); + ImBuf *pattern_ibuf = BKE_tracking_get_pattern_color_imbuf(ibuf, track, marker, TRUE); int j; zero_v3(site->color); From db7fd6b94c206ec583c783d405fb07f819ee7e80 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Sat, 2 Jun 2012 00:01:59 +0000 Subject: [PATCH 157/183] small code cleanup in inner loop of rasterizer --- intern/raskter/raskter.c | 4 +--- intern/raskter/raskter.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 279b1226e5f..152efb05cf0 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -307,9 +307,7 @@ int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_ if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { /* draw the pixels. */ - for (; cpxl <= mpxl; cpxl++) { - *cpxl = 1.0f; - } + for (; cpxl <= mpxl; *cpxl++ = 1.0f); } } diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h index 3292d4f8163..d94eb0b5886 100644 --- a/intern/raskter/raskter.h +++ b/intern/raskter/raskter.h @@ -50,7 +50,7 @@ extern "C" { int PLX_raskterize(float (*base_verts)[2], int num_base_verts, float *buf, int buf_x, int buf_y); - +int PLX_add_feather(float *base_verts, int num_base_verts, float *feather_verts, int num_feather_verts, float *buf, int buf_x, int buf_y, int negaive); int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*feather_verts)[2], int num_feather_verts, float *buf, int buf_x, int buf_y); From fea490c73e361409f4d52c787d9ceed9655adb13 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Sat, 2 Jun 2012 00:16:23 +0000 Subject: [PATCH 158/183] small code cleanup in rasterizer --- intern/raskter/raskter.h | 1 - 1 file changed, 1 deletion(-) diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h index d94eb0b5886..e80ca1d41c4 100644 --- a/intern/raskter/raskter.h +++ b/intern/raskter/raskter.h @@ -50,7 +50,6 @@ extern "C" { int PLX_raskterize(float (*base_verts)[2], int num_base_verts, float *buf, int buf_x, int buf_y); -int PLX_add_feather(float *base_verts, int num_base_verts, float *feather_verts, int num_feather_verts, float *buf, int buf_x, int buf_y, int negaive); int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*feather_verts)[2], int num_feather_verts, float *buf, int buf_x, int buf_y); From 49a0f8f73b3056a59b87a04b102132e16857602f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 3 Jun 2012 19:39:19 +0000 Subject: [PATCH 159/183] - adding subdivided points now interpolates weights along the spline. - the handle lengths are now interpolated based on the new points projected location along the spline. --- source/blender/blenkernel/BKE_mask.h | 3 ++- source/blender/blenkernel/intern/mask.c | 35 +++++++++++++++++++------ source/blender/editors/mask/mask_ops.c | 15 ++++++----- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 1eb130f1713..5128141499e 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -110,7 +110,8 @@ void BKE_mask_update_display(struct Mask *mask, float ctime); void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_newframe); void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe); void BKE_mask_parent_init(struct MaskParent *parent); -void BKE_mask_calc_handle_adjacent_length(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); +void BKE_mask_calc_handle_adjacent_interp(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, + const float u); void BKE_mask_calc_tangent_polyline(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, float t[2]); void BKE_mask_calc_handle_point(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); void BKE_mask_calc_handle_point_auto(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 407216f5578..5c7cdc7ef11 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1077,31 +1077,50 @@ static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dis } } -void BKE_mask_calc_handle_adjacent_length(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) +void BKE_mask_calc_handle_adjacent_interp(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, const float u) { /* TODO! - make this interpolate between siblings - not always midpoint! */ int length_tot = 0; float length_average = 0.0f; + float weight_average = 0.0f; + MaskSplinePoint *prev_point, *next_point; + + BLI_assert(u >= 0.0f && u <= 1.0f); + BKE_mask_get_handle_point_adjacent(mask, spline, point, &prev_point, &next_point); - if (prev_point) { - length_average += len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]); - length_tot++; - } + if (prev_point && next_point) { + length_average = ((len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]) * (1.0f - u)) + + (len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]) * u)); - if (next_point) { - length_average += len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]); - length_tot++; + weight_average = (prev_point->bezt.weight * (1.0f - u) + + next_point->bezt.weight * u); + length_tot = 1; + } + else { + if (prev_point) { + length_average += len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]); + weight_average += prev_point->bezt.weight; + length_tot++; + } + + if (next_point) { + length_average += len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]); + weight_average += next_point->bezt.weight; + length_tot++; + } } if (length_tot) { length_average /= (float)length_tot; + weight_average /= (float)length_tot; enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + point->bezt.weight = weight_average; } } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 010066f705f..f86711d1355 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -946,7 +946,7 @@ void MASK_OT_slide_point(wmOperatorType *ot) /******************** add vertex *********************/ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, - const float point_co[2], const float tangent[2], + const float point_co[2], const float tangent[2], const float u, MaskSplinePoint *reference_point, const short reference_adjacent) { MaskSplinePoint *prev_point = NULL; @@ -1008,7 +1008,7 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask add_v2_v2(bezt->vec[2], vec); if (reference_adjacent) { - BKE_mask_calc_handle_adjacent_length(mask, spline, new_point); + BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); } } else { @@ -1061,7 +1061,7 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask sub_v2_v2(bezt->vec[2], vec); #else BKE_mask_calc_handle_point_auto(mask, spline, new_point, TRUE); - BKE_mask_calc_handle_adjacent_length(mask, spline, new_point); + BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); #endif } @@ -1097,8 +1097,9 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) MaskSplinePoint *point = NULL; const float threshold = 9; float tangent[2]; + float u; - if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, NULL, tangent)) { + if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, &u, tangent)) { MaskSplinePoint *new_point; int point_index = point - spline->points; @@ -1108,7 +1109,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) new_point = &spline->points[point_index + 1]; - setup_vertex_point(C, mask, spline, new_point, co, tangent, NULL, TRUE); + setup_vertex_point(C, mask, spline, new_point, co, tangent, u, NULL, TRUE); /* TODO - we could pass the spline! */ BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index + 1, TRUE, TRUE); @@ -1249,7 +1250,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const masklay->act_point = new_point; - setup_vertex_point(C, mask, spline, new_point, co, NULL, ref_point, FALSE); + setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE); if (masklay->splines_shapes.first) { point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); @@ -1295,7 +1296,7 @@ static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const flo masklay->act_point = new_point; - setup_vertex_point(C, mask, spline, new_point, co, NULL, ref_point, FALSE); + setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE); { int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); From 5cf12e9a7866fe4f4797da08ec8811860612e64b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 07:48:10 +0000 Subject: [PATCH 160/183] border select was removed from modal keymap by mistake --- source/blender/windowmanager/intern/wm_operators.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 0c4454c7f7b..d7d55885f37 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3937,6 +3937,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "UV_OT_select_border"); WM_modalkeymap_assign(keymap, "CLIP_OT_select_border"); WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_border"); + WM_modalkeymap_assign(keymap, "MASK_OT_select_border"); WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border"); From efaeeaf15b4a5e1a404fbe51be922d1f245b5d65 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 08:01:59 +0000 Subject: [PATCH 161/183] fix for selecting UW's --- source/blender/editors/mask/mask_select.c | 32 +++++++++++++++++------ 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 95c2808bc3e..323721e2dfe 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -240,9 +240,10 @@ static int select_exec(bContext *C, wmOperator *op) point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &is_handle, NULL); + if (extend == 0 && deselect == 0 && toggle == 0) + ED_mask_select_toggle_all(mask, SEL_DESELECT); + if (point) { - if (extend == 0 && deselect == 0 && toggle == 0) - ED_mask_select_toggle_all(mask, SEL_DESELECT); if (is_handle) { if (extend) { @@ -302,14 +303,29 @@ static int select_exec(bContext *C, wmOperator *op) MaskSplinePointUW *uw; if (ED_mask_feather_find_nearest(C, mask, co, threshold, &masklay, &spline, &point, &uw, NULL)) { - if (!extend) - ED_mask_select_toggle_all(mask, SEL_DESELECT); - if (uw) - uw->flag |= SELECT; + if (extend) { + masklay->act_spline = spline; + masklay->act_point = point; - masklay->act_spline = spline; - masklay->act_point = point; + if (uw) uw->flag |= SELECT; + } + else if (deselect) { + if (uw) uw->flag &= ~SELECT; + } + else { + masklay->act_spline = spline; + masklay->act_point = point; + + if (uw) { + if (!(uw->flag & SELECT)) { + uw->flag |= SELECT; + } + else if (toggle) { + uw->flag &= ~SELECT; + } + } + } ED_mask_select_flush_all(mask); From 90d7e25b4fe6191b0b433d4e1cf900b90811bd83 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 11:25:02 +0000 Subject: [PATCH 162/183] add select linked operator, works as with meshes. --- source/blender/blenkernel/BKE_mask.h | 4 +- source/blender/blenkernel/intern/mask.c | 10 +- source/blender/editors/mask/mask_editor.c | 8 ++ source/blender/editors/mask/mask_intern.h | 7 +- source/blender/editors/mask/mask_ops.c | 2 +- source/blender/editors/mask/mask_select.c | 145 +++++++++++++++++++--- 6 files changed, 148 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 5128141499e..a26934f103b 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -91,8 +91,8 @@ float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *p struct MaskSplinePointUW *BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw); void BKE_mask_point_add_uw(struct MaskSplinePoint *point, float u, float w); -void BKE_mask_point_select_set(struct MaskSplinePoint *point, int select); -void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, int select); +void BKE_mask_point_select_set(struct MaskSplinePoint *point, const short do_select); +void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const short do_select); /* general */ struct Mask *BKE_mask_new(const char *name); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 5c7cdc7ef11..52225a1fab0 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -673,11 +673,11 @@ void BKE_mask_point_add_uw(MaskSplinePoint *point, float u, float w) BKE_mask_point_sort_uw(point, &point->uw[point->tot_uw - 1]); } -void BKE_mask_point_select_set(MaskSplinePoint *point, int select) +void BKE_mask_point_select_set(MaskSplinePoint *point, const short do_select) { int i; - if (select) { + if (do_select) { MASKPOINT_SEL_ALL(point); } else { @@ -685,7 +685,7 @@ void BKE_mask_point_select_set(MaskSplinePoint *point, int select) } for (i = 0; i < point->tot_uw; i++) { - if (select) { + if (do_select) { point->uw[i].flag |= SELECT; } else { @@ -694,9 +694,9 @@ void BKE_mask_point_select_set(MaskSplinePoint *point, int select) } } -void BKE_mask_point_select_set_handle(MaskSplinePoint *point, int select) +void BKE_mask_point_select_set_handle(MaskSplinePoint *point, const short do_select) { - if (select) { + if (do_select) { MASKPOINT_SEL_HANDLE(point); } else { diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index 778990726e5..8e93086eec8 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -204,6 +204,8 @@ void ED_operatortypes_mask(void) WM_operatortype_append(MASK_OT_select_border); WM_operatortype_append(MASK_OT_select_lasso); WM_operatortype_append(MASK_OT_select_circle); + WM_operatortype_append(MASK_OT_select_linked_pick); + WM_operatortype_append(MASK_OT_select_linked); /* hide/reveal */ WM_operatortype_append(MASK_OT_hide_view_clear); @@ -258,6 +260,12 @@ void ED_keymap_mask(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0); RNA_enum_set(kmi->ptr, "action", SEL_INVERT); + WM_keymap_add_item(keymap, "MASK_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "deselect", TRUE); + WM_keymap_add_item(keymap, "MASK_OT_select_border", BKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_select_circle", CKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 5940b76abf0..af1ad96ee17 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -77,12 +77,15 @@ void MASK_OT_select_all(struct wmOperatorType *ot); void MASK_OT_select_border(struct wmOperatorType *ot); void MASK_OT_select_lasso(struct wmOperatorType *ot); void MASK_OT_select_circle(struct wmOperatorType *ot); +void MASK_OT_select_linked_pick(struct wmOperatorType *ot); +void MASK_OT_select_linked(struct wmOperatorType *ot); -int ED_mask_spline_select_check(struct MaskSplinePoint *points, int tot_point); +int ED_mask_spline_select_check(struct MaskSpline *spline); int ED_mask_layer_select_check(struct MaskLayer *masklay); int ED_mask_select_check(struct Mask *mask); -void ED_mask_layer_select_set(struct MaskLayer *masklay, int select); +void ED_mask_spline_select_set(struct MaskSpline *spline, const short do_select); +void ED_mask_layer_select_set(struct MaskLayer *masklay, const short do_select); void ED_mask_select_toggle_all(struct Mask *mask, int action); void ED_mask_select_flush_all(struct Mask *mask); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index f86711d1355..a6954fc8ac6 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1487,7 +1487,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) } for (spline = masklay->splines.first; spline; spline = spline->next) { - if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { + if (ED_mask_spline_select_check(spline)) { spline->flag ^= MASK_SPLINE_CYCLIC; } } diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 323721e2dfe..18d745dcf7b 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -57,12 +57,13 @@ #include "mask_intern.h" /* own include */ -int ED_mask_spline_select_check(MaskSplinePoint *points, int tot_point) +/* 'check' select */ +int ED_mask_spline_select_check(MaskSpline *spline) { int i; - for (i = 0; i < tot_point; i++) { - MaskSplinePoint *point = &points[i]; + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; if (MASKPOINT_ISSEL_ANY(point)) return TRUE; @@ -80,7 +81,7 @@ int ED_mask_layer_select_check(MaskLayer *masklay) } for (spline = masklay->splines.first; spline; spline = spline->next) { - if (ED_mask_spline_select_check(spline->points, spline->tot_point)) { + if (ED_mask_spline_select_check(spline)) { return TRUE; } } @@ -101,29 +102,35 @@ int ED_mask_select_check(Mask *mask) return FALSE; } -void ED_mask_layer_select_set(MaskLayer *masklay, int select) +/* 'sel' select */ +void ED_mask_spline_select_set(MaskSpline *spline, const short do_select) +{ + int i; + + if (do_select) + spline->flag |= SELECT; + else + spline->flag &= ~SELECT; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + BKE_mask_point_select_set(point, do_select); + } +} + +void ED_mask_layer_select_set(MaskLayer *masklay, const short do_select) { MaskSpline *spline; if (masklay->restrictflag & MASK_RESTRICT_SELECT) { - if (select == TRUE) { + if (do_select == TRUE) { return; } } for (spline = masklay->splines.first; spline; spline = spline->next) { - int i; - - if (select) - spline->flag |= SELECT; - else - spline->flag &= ~SELECT; - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - - BKE_mask_point_select_set(point, select); - } + ED_mask_spline_select_set(spline, do_select); } } @@ -659,3 +666,105 @@ void MASK_OT_select_circle(wmOperatorType *ot) RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); } + +static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + float co[2]; + int do_select = !RNA_boolean_get(op->ptr, "deselect"); + + int is_handle = 0; + const float threshold = 19; + int change = FALSE; + + ED_mask_mouse_pos(C, event, co); + + point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &is_handle, NULL); + + if (point) { + ED_mask_spline_select_set(spline, do_select); + masklay->act_spline = spline; + masklay->act_point = point; + + change = TRUE; + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_select_linked_pick(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Linked"; + ot->idname = "MASK_OT_select_linked_pick"; + ot->description = "(De)select all points linked to the curve under the mouse cursor"; + + /* api callbacks */ + ot->invoke = mask_select_linked_pick_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); +} + +static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + int change = FALSE; + + /* do actual selection */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + if (ED_mask_spline_select_check(spline)) { + ED_mask_spline_select_set(spline, TRUE); + change = TRUE; + } + } + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_select_linked(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Linked All"; + ot->idname = "MASK_OT_select_linked"; + ot->description = "Select all vertices linked to the active mesh"; + + /* api callbacks */ + ot->exec = mask_select_linked_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} From c357041e0a3a6291f9f07180b37ea80064cf23c5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 13:24:10 +0000 Subject: [PATCH 163/183] operator to switch direction --- release/scripts/startup/bl_ui/space_clip.py | 2 + source/blender/blenkernel/BKE_mask.h | 5 +- source/blender/blenkernel/intern/mask.c | 78 +++++++++++++++++++++ source/blender/editors/mask/mask_editor.c | 1 + source/blender/editors/mask/mask_intern.h | 1 + source/blender/editors/mask/mask_ops.c | 52 ++++++++++++++ 6 files changed, 138 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 1c94b4db95e..0450e0c615c 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -394,6 +394,7 @@ class CLIP_PT_tools_mask(CLIP_PT_mask_view_panel, Panel): col.label(text="Spline:") col.operator("mask.delete") col.operator("mask.cyclic_toggle") + col.operator("mask.switch_direction") col = layout.column(align=True) col.label(text="Parenting:") @@ -1196,6 +1197,7 @@ class CLIP_MT_mask(Menu): layout.separator() layout.operator("mask.cyclic_toggle") + layout.operator("mask.switch_direction") layout.separator() layout.operator("mask.parent_clear") diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index a26934f103b..32493e4e445 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -63,10 +63,13 @@ float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, float (*BKE_mask_spline_differentiate_with_resolution(struct MaskSpline *spline, int width, int height, int *tot_diff_point))[2]; float (*BKE_mask_spline_feather_differentiated_points_with_resolution(struct MaskSpline *spline, - int width, int height, int *tot_feather_point))[2]; + int width, int height, int *tot_feather_point))[2]; float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2]; +void BKE_mask_point_direction_switch(struct MaskSplinePoint *point); +void BKE_mask_spline_direction_switch(struct MaskLayer *masklay, struct MaskSpline *spline); + /* point */ int BKE_mask_point_has_handle(struct MaskSplinePoint *point); void BKE_mask_point_handle(struct MaskSplinePoint *point, float handle[2]); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 52225a1fab0..f2c1d9f8b65 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -377,6 +377,84 @@ float (*BKE_mask_spline_feather_points(MaskSpline * spline, int *tot_feather_poi return feather; } +void BKE_mask_point_direction_switch(MaskSplinePoint *point) +{ + const int tot_uw = point->tot_uw; + const int tot_uw_half = tot_uw / 2; + int i; + + if (tot_uw < 2) { + return; + } + + /* count */ + for (i = 0; i < tot_uw_half; i++) { + MaskSplinePointUW *uw_a = &point->uw[i]; + MaskSplinePointUW *uw_b = &point->uw[tot_uw - (i + 1)]; + SWAP(MaskSplinePointUW, *uw_a, *uw_b); + } + for (i = 0; i < tot_uw; i++) { + MaskSplinePointUW *uw = &point->uw[i]; + uw->u = 1.0f - uw->u; + } +} + +//typedef (float)[MASK_OBJECT_SHAPE_ELEM_SIZE] MaskLayerShapeElem; + +typedef struct MaskLayerShapeElem { + float value[MASK_OBJECT_SHAPE_ELEM_SIZE]; +} MaskLayerShapeElem; + +void BKE_mask_spline_direction_switch(MaskLayer *masklay, MaskSpline *spline) +{ + const int tot_point = spline->tot_point; + const int tot_point_half = tot_point / 2; + int i, i_prev; + + if (tot_point < 2) { + return; + } + + /* count */ + for (i = 0; i < tot_point_half; i++) { + MaskSplinePoint *point_a = &spline->points[i]; + MaskSplinePoint *point_b = &spline->points[tot_point - (i + 1)]; + SWAP(MaskSplinePoint, *point_a, *point_b); + } + + /* correct UW's */ + i_prev = tot_point - 1; + for (i = 0; i < tot_point; i++) { + + BKE_mask_point_direction_switch(&spline->points[i]); + + SWAP(MaskSplinePointUW *, spline->points[i].uw, spline->points[i_prev].uw); + SWAP(int, spline->points[i].tot_uw, spline->points[i_prev].tot_uw); + + i_prev = i; + } + + /* correct animation */ + if (masklay->splines_shapes.first) { + MaskLayerShape *masklay_shape; + + const int spline_index = BKE_mask_layer_shape_spline_to_index(masklay, spline); + + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + MaskLayerShapeElem *fp_arr = (MaskLayerShapeElem *)masklay_shape->data; + + for (i = 0; i < tot_point_half; i++) { + MaskLayerShapeElem *fp_a = &fp_arr[spline_index + (i) ]; + MaskLayerShapeElem *fp_b = &fp_arr[spline_index + (tot_point - (i + 1))]; + SWAP(MaskLayerShapeElem, *fp_a, *fp_b); + } + } + } +} + /* point */ int BKE_mask_point_has_handle(MaskSplinePoint *point) diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_editor.c index 8e93086eec8..96d645569c5 100644 --- a/source/blender/editors/mask/mask_editor.c +++ b/source/blender/editors/mask/mask_editor.c @@ -196,6 +196,7 @@ void ED_operatortypes_mask(void) /* geometry */ WM_operatortype_append(MASK_OT_add_vertex); WM_operatortype_append(MASK_OT_add_feather_vertex); + WM_operatortype_append(MASK_OT_switch_direction); WM_operatortype_append(MASK_OT_delete); /* select */ diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index af1ad96ee17..f2e862a7d8b 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -53,6 +53,7 @@ void MASK_OT_delete(struct wmOperatorType *ot); void MASK_OT_hide_view_clear(struct wmOperatorType *ot); void MASK_OT_hide_view_set(struct wmOperatorType *ot); +void MASK_OT_switch_direction(struct wmOperatorType *ot); void MASK_OT_handle_type_set(struct wmOperatorType *ot); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index a6954fc8ac6..3f2e82b1ca8 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1657,6 +1657,58 @@ void MASK_OT_delete(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* *** switch direction *** */ +static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + int change = FALSE; + + /* do actual selection */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + if (ED_mask_spline_select_check(spline)) { + BKE_mask_spline_direction_switch(masklay, spline); + change = TRUE; + } + } + } + + if (change) { + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_switch_direction(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Switch Direction"; + ot->description = "Switch direction of selected splines"; + ot->idname = "MASK_OT_switch_direction"; + + /* api callbacks */ + ot->exec = mask_switch_direction_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + + /******************** set handle type *********************/ static int set_handle_type_exec(bContext *C, wmOperator *op) From 7cd7a887407d254ca3ac5bff77c3e4b6a42a4307 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 13:46:38 +0000 Subject: [PATCH 164/183] code cleanup --- source/blender/blenkernel/BKE_mask.h | 10 +++++----- source/blender/blenkernel/intern/mask.c | 8 ++++---- source/blender/editors/mask/mask_ops.c | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 32493e4e445..89c8a76f841 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -129,13 +129,13 @@ int BKE_mask_layer_shape_totvert(struct MaskLayer *masklay); void BKE_mask_layer_shape_from_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); void BKE_mask_layer_shape_to_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); void BKE_mask_layer_shape_to_mask_interp(struct MaskLayer *masklay, - struct MaskLayerShape *masklay_shape_a, - struct MaskLayerShape *masklay_shape_b, - const float fac); + struct MaskLayerShape *masklay_shape_a, + struct MaskLayerShape *masklay_shape_b, + const float fac); struct MaskLayerShape *BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, int frame); int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, int frame, - struct MaskLayerShape **r_masklay_shape_a, - struct MaskLayerShape **r_masklay_shape_b); + struct MaskLayerShape **r_masklay_shape_a, + struct MaskLayerShape **r_masklay_shape_b); struct MaskLayerShape *BKE_mask_layer_shape_varify_frame(struct MaskLayer *masklay, int frame); void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); void BKE_mask_layer_shape_sort(struct MaskLayer *masklay); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index f2c1d9f8b65..41f8cb1ddd2 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -325,12 +325,12 @@ float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline return feather; } -float (*BKE_mask_spline_feather_differentiated_points(MaskSpline * spline, int *tot_feather_point))[2] +float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2] { return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point); } -float (*BKE_mask_spline_feather_points(MaskSpline * spline, int *tot_feather_point))[2] +float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -1939,8 +1939,8 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) diff_points = BKE_mask_spline_differentiate_with_resolution(spline, width, height, &tot_diff_point); if (tot_diff_point) { diff_feather_points = - BKE_mask_spline_feather_differentiated_points_with_resolution(spline, width, height, - &tot_diff_feather_points); + BKE_mask_spline_feather_differentiated_points_with_resolution(spline, width, height, + &tot_diff_feather_points); } /* TODO, make this optional! */ diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 3f2e82b1ca8..7dc486fe40c 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -357,8 +357,8 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c if (feather) { feather_points = BKE_mask_point_segment_feather_diff_with_resolution(spline, cur_point, - width, height, - &tot_feather_point); + width, height, + &tot_feather_point); points = feather_points; tot_point = tot_feather_point; From 009798814574028f93b68ffdd8db2e8238c3dece Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 13:51:36 +0000 Subject: [PATCH 165/183] rename mask file --- source/blender/editors/mask/CMakeLists.txt | 2 +- source/blender/editors/mask/{mask_editor.c => mask_edit.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename source/blender/editors/mask/{mask_editor.c => mask_edit.c} (100%) diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index e6f26e32c06..2a772653506 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -38,7 +38,7 @@ set(INC_SYS set(SRC mask_draw.c - mask_editor.c + mask_edit.c mask_ops.c mask_relationships.c mask_select.c diff --git a/source/blender/editors/mask/mask_editor.c b/source/blender/editors/mask/mask_edit.c similarity index 100% rename from source/blender/editors/mask/mask_editor.c rename to source/blender/editors/mask/mask_edit.c From 7b8ee679337994c6da0f5785282f6cb5ea837df9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 14:27:13 +0000 Subject: [PATCH 166/183] split mask add functions into their own file. --- source/blender/blenkernel/BKE_mask.h | 1 + source/blender/blenkernel/intern/mask.c | 63 ++ source/blender/editors/mask/CMakeLists.txt | 1 + source/blender/editors/mask/mask_add.c | 707 ++++++++++++++++++++ source/blender/editors/mask/mask_edit.c | 4 +- source/blender/editors/mask/mask_intern.h | 7 +- source/blender/editors/mask/mask_ops.c | 710 +-------------------- 7 files changed, 780 insertions(+), 713 deletions(-) create mode 100644 source/blender/editors/mask/mask_add.c diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 89c8a76f841..3f837f995ce 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -69,6 +69,7 @@ float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feath void BKE_mask_point_direction_switch(struct MaskSplinePoint *point); void BKE_mask_spline_direction_switch(struct MaskLayer *masklay, struct MaskSpline *spline); +float BKE_mask_spline_project_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float start_u, const float co[2]); /* point */ int BKE_mask_point_has_handle(struct MaskSplinePoint *point); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 41f8cb1ddd2..870a84df66a 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -455,6 +455,69 @@ void BKE_mask_spline_direction_switch(MaskLayer *masklay, MaskSpline *spline) } } + +float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, float start_u, const float co[2]) +{ + const float proj_eps = 1e-3; + const float proj_eps_squared = proj_eps * proj_eps; + const int N = 1000; + float u = -1.0f, du = 1.0f / N, u1 = start_u, u2 = start_u; + float ang = -1.0f; + + while (u1 > 0.0f || u2 < 1.0f) { + float n1[2], n2[2], co1[2], co2[2]; + float v1[2], v2[2]; + float ang1, ang2; + + if (u1 >= 0.0f) { + BKE_mask_point_segment_co(spline, point, u1, co1); + BKE_mask_point_normal(spline, point, u1, n1); + sub_v2_v2v2(v1, co, co1); + + if (len_squared_v2(v1) > proj_eps_squared) { + ang1 = angle_v2v2(v1, n1); + if (ang1 > M_PI / 2.0f) + ang1 = M_PI - ang1; + + if (ang < 0.0f || ang1 < ang) { + ang = ang1; + u = u1; + } + } + else { + u = u1; + break; + } + } + + if (u2 <= 1.0f) { + BKE_mask_point_segment_co(spline, point, u2, co2); + BKE_mask_point_normal(spline, point, u2, n2); + sub_v2_v2v2(v2, co, co2); + + if (len_squared_v2(v2) > proj_eps_squared) { + ang2 = angle_v2v2(v2, n2); + if (ang2 > M_PI / 2.0f) + ang2 = M_PI - ang2; + + if (ang2 < ang) { + ang = ang2; + u = u2; + } + } + else { + u = u2; + break; + } + } + + u1 -= du; + u2 += du; + } + + return u; +} + /* point */ int BKE_mask_point_has_handle(MaskSplinePoint *point) diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index 2a772653506..f15e9c27732 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -37,6 +37,7 @@ set(INC_SYS ) set(SRC + mask_add.c mask_draw.c mask_edit.c mask_ops.c diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c new file mode 100644 index 00000000000..62675635b7b --- /dev/null +++ b/source/blender/editors/mask/mask_add.c @@ -0,0 +1,707 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_add.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "DNA_scene_types.h" +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" +#include "ED_keyframing.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" /* own include */ + + +static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_co[2], int threshold, int feather, + MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + float *u_r, float tangent[2]) +{ + MaskLayer *masklay, *point_masklay; + MaskSpline *point_spline; + MaskSplinePoint *point = NULL; + float dist, co[2]; + int width, height; + float u; + float scalex, scaley, aspx, aspy; + + ED_mask_size(C, &width, &height); + ED_mask_aspect(C, &aspx, &aspy); + ED_mask_pixelspace_factor(C, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *cur_point = &spline->points[i]; + float *diff_points; + int tot_diff_point; + + diff_points = BKE_mask_point_segment_diff_with_resolution(spline, cur_point, width, height, + &tot_diff_point); + + if (diff_points) { + int i, tot_feather_point, tot_point; + float *feather_points = NULL, *points; + + if (feather) { + feather_points = BKE_mask_point_segment_feather_diff_with_resolution(spline, cur_point, + width, height, + &tot_feather_point); + + points = feather_points; + tot_point = tot_feather_point; + } + else { + points = diff_points; + tot_point = tot_diff_point; + } + + for (i = 0; i < tot_point - 1; i++) { + float cur_dist, a[2], b[2]; + + a[0] = points[2 * i] * scalex; + a[1] = points[2 * i + 1] * scaley; + + b[0] = points[2 * i + 2] * scalex; + b[1] = points[2 * i + 3] * scaley; + + cur_dist = dist_to_line_segment_v2(co, a, b); + + if (point == NULL || cur_dist < dist) { + if (tangent) + sub_v2_v2v2(tangent, &diff_points[2 * i + 2], &diff_points[2 * i]); + + point_masklay = masklay; + point_spline = spline; + point = cur_point; + dist = cur_dist; + u = (float)i / tot_point; + + } + } + + if (feather_points) + MEM_freeN(feather_points); + + MEM_freeN(diff_points); + } + } + } + } + + if (point && dist < threshold) { + if (masklay_r) + *masklay_r = point_masklay; + + if (spline_r) + *spline_r = point_spline; + + if (point_r) + *point_r = point; + + if (u_r) { + u = BKE_mask_spline_project_co(point_spline, point, u, normal_co); + + *u_r = u; + } + + return TRUE; + } + + if (masklay_r) + *masklay_r = NULL; + + if (spline_r) + *spline_r = NULL; + + if (point_r) + *point_r = NULL; + + return FALSE; +} + +/******************** add vertex *********************/ + +static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, + const float point_co[2], const float tangent[2], const float u, + MaskSplinePoint *reference_point, const short reference_adjacent) +{ + MaskSplinePoint *prev_point = NULL; + MaskSplinePoint *next_point = NULL; + BezTriple *bezt; + int width, height; + float co[3]; + const float len = 20.0; /* default length of handle in pixel space */ + + copy_v2_v2(co, point_co); + co[2] = 0.0f; + + ED_mask_size(C, &width, &height); + + /* point coordinate */ + bezt = &new_point->bezt; + + bezt->h1 = bezt->h2 = HD_ALIGN; + + if (reference_point) { + bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1); + } + else if (reference_adjacent) { + if (spline->tot_point != 1) { + int index = (int)(new_point - spline->points); + prev_point = &spline->points[(index - 1) % spline->tot_point]; + next_point = &spline->points[(index + 1) % spline->tot_point]; + + bezt->h1 = bezt->h2 = MAX2(prev_point->bezt.h2, next_point->bezt.h1); + + /* note, we may want to copy other attributes later, radius? pressure? color? */ + } + } + + copy_v3_v3(bezt->vec[0], co); + copy_v3_v3(bezt->vec[1], co); + copy_v3_v3(bezt->vec[2], co); + + /* initial offset for handles */ + if (spline->tot_point == 1) { + /* first point of splien is aligned horizontally */ + bezt->vec[0][0] -= len / width; + bezt->vec[2][0] += len / width; + } + else if (tangent) { + float vec[2]; + + copy_v2_v2(vec, tangent); + + vec[0] *= width; + vec[1] *= height; + + mul_v2_fl(vec, len / len_v2(vec)); + + vec[0] /= width; + vec[1] /= height; + + sub_v2_v2(bezt->vec[0], vec); + add_v2_v2(bezt->vec[2], vec); + + if (reference_adjacent) { + BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); + } + } + else { + + /* calculating auto handles works much nicer */ +#if 0 + /* next points are aligning in the direction of previous/next point */ + MaskSplinePoint *point; + float v1[2], v2[2], vec[2]; + float dir = 1.0f; + + if (new_point == spline->points) { + point = new_point + 1; + dir = -1.0f; + } + else + point = new_point - 1; + + if (spline->tot_point < 3) { + v1[0] = point->bezt.vec[1][0] * width; + v1[1] = point->bezt.vec[1][1] * height; + + v2[0] = new_point->bezt.vec[1][0] * width; + v2[1] = new_point->bezt.vec[1][1] * height; + } + else { + if (new_point == spline->points) { + v1[0] = spline->points[1].bezt.vec[1][0] * width; + v1[1] = spline->points[1].bezt.vec[1][1] * height; + + v2[0] = spline->points[spline->tot_point - 1].bezt.vec[1][0] * width; + v2[1] = spline->points[spline->tot_point - 1].bezt.vec[1][1] * height; + } + else { + v1[0] = spline->points[0].bezt.vec[1][0] * width; + v1[1] = spline->points[0].bezt.vec[1][1] * height; + + v2[0] = spline->points[spline->tot_point - 2].bezt.vec[1][0] * width; + v2[1] = spline->points[spline->tot_point - 2].bezt.vec[1][1] * height; + } + } + + sub_v2_v2v2(vec, v1, v2); + mul_v2_fl(vec, len * dir / len_v2(vec)); + + vec[0] /= width; + vec[1] /= height; + + add_v2_v2(bezt->vec[0], vec); + sub_v2_v2(bezt->vec[2], vec); +#else + BKE_mask_calc_handle_point_auto(mask, spline, new_point, TRUE); + BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); + +#endif + } + + BKE_mask_parent_init(&new_point->parent); + + /* select new point */ + MASKPOINT_SEL_ALL(new_point); + ED_mask_select_flush_all(mask); +} + + +/* **** add extrude vertex **** */ + +static void finSelectedSplinePoint(MaskLayer *masklay, MaskSpline **spline, MaskSplinePoint **point, short check_active) +{ + MaskSpline *cur_spline = masklay->splines.first; + + *spline = NULL; + *point = NULL; + + if (check_active) { + if (masklay->act_spline && masklay->act_point) { + *spline = masklay->act_spline; + *point = masklay->act_point; + return; + } + } + + while (cur_spline) { + int i; + + for (i = 0; i < cur_spline->tot_point; i++) { + MaskSplinePoint *cur_point = &cur_spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(cur_point)) { + if (*spline != NULL && *spline != cur_spline) { + *spline = NULL; + *point = NULL; + return; + } + else if (*point) { + *point = NULL; + } + else { + *spline = cur_spline; + *point = cur_point; + } + } + } + + cur_spline = cur_spline->next; + } +} + +/* **** add subdivide vertex **** */ + +static void mask_spline_add_point_at_index(MaskSpline *spline, int point_index) +{ + MaskSplinePoint *new_point_array; + + new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); + + memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * (point_index + 1)); + memcpy(new_point_array + point_index + 2, spline->points + point_index + 1, + sizeof(MaskSplinePoint) * (spline->tot_point - point_index - 1)); + + MEM_freeN(spline->points); + spline->points = new_point_array; + spline->tot_point++; +} + +static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) +{ + MaskLayer *masklay; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + const float threshold = 9; + float tangent[2]; + float u; + + if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, &u, tangent)) { + MaskSplinePoint *new_point; + int point_index = point - spline->points; + + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + mask_spline_add_point_at_index(spline, point_index); + + new_point = &spline->points[point_index + 1]; + + setup_vertex_point(C, mask, spline, new_point, co, tangent, u, NULL, TRUE); + + /* TODO - we could pass the spline! */ + BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index + 1, TRUE, TRUE); + + masklay->act_point = new_point; + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return TRUE; + } + + return FALSE; +} + +static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2]) +{ + MaskSpline *spline; + MaskSplinePoint *point; + MaskSplinePoint *new_point = NULL, *ref_point = NULL; + + /* check on which side we want to add the point */ + int point_index; + float tangent_point[2]; + float tangent_co[2]; + int do_cyclic_correct = FALSE; + int do_recalc_src = FALSE; /* when extruding from endpoints only */ + int do_prev; /* use prev point rather then next?? */ + + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + if (!masklay) { + return FALSE; + } + else { + finSelectedSplinePoint(masklay, &spline, &point, TRUE); + } + + point_index = (point - spline->points); + + MASKPOINT_DESEL_ALL(point); + + if ((spline->flag & MASK_SPLINE_CYCLIC) || + (point_index > 0 && point_index != spline->tot_point - 1)) + { + BKE_mask_calc_tangent_polyline(mask, spline, point, tangent_point); + sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]); + + if (dot_v2v2(tangent_point, tangent_co) < 0.0f) { + do_prev = TRUE; + } + else { + do_prev = FALSE; + } + } + else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == 0)) { + do_prev = TRUE; + do_recalc_src = TRUE; + } + else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == spline->tot_point - 1)) { + do_prev = FALSE; + do_recalc_src = TRUE; + } + else { + /* should never get here */ + BLI_assert(0); + } + + /* use the point before the active one */ + if (do_prev) { + point_index--; + if (point_index < 0) { + point_index += spline->tot_point; /* wrap index */ + if ((spline->flag & MASK_SPLINE_CYCLIC) == 0) { + do_cyclic_correct = TRUE; + point_index = 0; + } + } + } + +// print_v2("", tangent_point); +// printf("%d\n", point_index); + + mask_spline_add_point_at_index(spline, point_index); + + if (do_cyclic_correct) { + ref_point = &spline->points[point_index + 1]; + new_point = &spline->points[point_index]; + *ref_point = *new_point; + memset(new_point, 0, sizeof(*new_point)); + } + else { + ref_point = &spline->points[point_index]; + new_point = &spline->points[point_index + 1]; + } + + masklay->act_point = new_point; + + setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE); + + if (masklay->splines_shapes.first) { + point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); + BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, TRUE, TRUE); + } + + if (do_recalc_src) { + /* TODO, update keyframes in time */ + BKE_mask_calc_handle_point_auto(mask, spline, ref_point, FALSE); + } + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return TRUE; +} + +static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2]) +{ + MaskSpline *spline; + MaskSplinePoint *point; + MaskSplinePoint *new_point = NULL, *ref_point = NULL; + + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + if (!masklay) { + /* if there's no masklay currently operationg on, create new one */ + masklay = BKE_mask_layer_new(mask, ""); + mask->masklay_act = mask->masklay_tot - 1; + spline = NULL; + point = NULL; + } + else { + finSelectedSplinePoint(masklay, &spline, &point, TRUE); + } + + if (!spline) { + /* no selected splines in active masklay, create new spline */ + spline = BKE_mask_spline_add(masklay); + } + + masklay->act_spline = spline; + new_point = spline->points; + + masklay->act_point = new_point; + + setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE); + + { + int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); + BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, TRUE, TRUE); + } + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return TRUE; +} + +static int add_vertex_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + float co[2]; + + masklay = BKE_mask_layer_active(mask); + + if (masklay && masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + masklay = NULL; + } + + RNA_float_get_array(op->ptr, "location", co); + + if (masklay && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) { + + /* cheap trick - double click for cyclic */ + MaskSpline *spline = masklay->act_spline; + MaskSplinePoint *point = masklay->act_point; + + int is_sta = (point == spline->points); + int is_end = (point == &spline->points[spline->tot_point - 1]); + + /* then check are we overlapping the mouse */ + if ((is_sta || is_end) && equals_v2v2(co, point->bezt.vec[1])) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + /* nothing to do */ + return OPERATOR_CANCELLED; + } + else { + /* recalc the connecting point as well to make a nice even curve */ + MaskSplinePoint *point_other = is_end ? spline->points : &spline->points[spline->tot_point - 1]; + spline->flag |= MASK_SPLINE_CYCLIC; + + /* TODO, update keyframes in time */ + BKE_mask_calc_handle_point_auto(mask, spline, point, FALSE); + BKE_mask_calc_handle_point_auto(mask, spline, point_other, FALSE); + + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + return OPERATOR_FINISHED; + } + } + + if (!add_vertex_subdivide(C, mask, co)) { + if (!add_vertex_extrude(C, mask, masklay, co)) { + return OPERATOR_CANCELLED; + } + } + } + else { + if (!add_vertex_subdivide(C, mask, co)) { + if (!add_vertex_new(C, mask, masklay, co)) { + return OPERATOR_CANCELLED; + } + } + } + + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + + return OPERATOR_FINISHED; +} + +static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + float co[2]; + + ED_mask_mouse_pos(C, event, co); + + RNA_float_set_array(op->ptr, "location", co); + + return add_vertex_exec(C, op); +} + +void MASK_OT_add_vertex(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Vertex"; + ot->description = "Add vertex to active spline"; + ot->idname = "MASK_OT_add_vertex"; + + /* api callbacks */ + ot->exec = add_vertex_exec; + ot->invoke = add_vertex_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); +} + +/******************** add feather vertex *********************/ + +static int add_feather_vertex_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + const float threshold = 9; + float co[2], u; + + RNA_float_get_array(op->ptr, "location", co); + + point = ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL); + if (point) + return OPERATOR_FINISHED; + + if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &masklay, &spline, &point, &u, NULL)) { + Scene *scene = CTX_data_scene(C); + float w = BKE_mask_point_weight(spline, point, u); + + BKE_mask_point_add_uw(point, u, w); + + BKE_mask_update_display(mask, scene->r.cfra); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +static int add_feather_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + float co[2]; + + ED_mask_mouse_pos(C, event, co); + + RNA_float_set_array(op->ptr, "location", co); + + return add_feather_vertex_exec(C, op); +} + +void MASK_OT_add_feather_vertex(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add feather Vertex"; + ot->description = "Add vertex to feather"; + ot->idname = "MASK_OT_add_feather_vertex"; + + /* api callbacks */ + ot->exec = add_feather_vertex_exec; + ot->invoke = add_feather_vertex_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); +} diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 96d645569c5..0b8551ddd4c 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -193,9 +193,11 @@ void ED_operatortypes_mask(void) WM_operatortype_append(MASK_OT_layer_new); WM_operatortype_append(MASK_OT_layer_remove); - /* geometry */ + /* add */ WM_operatortype_append(MASK_OT_add_vertex); WM_operatortype_append(MASK_OT_add_feather_vertex); + + /* geometry */ WM_operatortype_append(MASK_OT_switch_direction); WM_operatortype_append(MASK_OT_delete); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index f2e862a7d8b..70f13abd44f 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -38,13 +38,14 @@ struct wmOperatorType; /* internal exports only */ +/* mask_add.c */ +void MASK_OT_add_vertex(struct wmOperatorType *ot); +void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); + /* mask_ops.c */ void MASK_OT_new(struct wmOperatorType *ot); void MASK_OT_layer_new(struct wmOperatorType *ot); void MASK_OT_layer_remove(struct wmOperatorType *ot); - -void MASK_OT_add_vertex(struct wmOperatorType *ot); -void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); void MASK_OT_cyclic_toggle(struct wmOperatorType *ot); void MASK_OT_slide_point(struct wmOperatorType *ot); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 7dc486fe40c..cf3a72bdc78 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -59,68 +59,6 @@ /******************** utility functions *********************/ -static float projection_on_spline(MaskSpline *spline, MaskSplinePoint *point, float start_u, const float co[2]) -{ - const float proj_eps = 1e-3; - const float proj_eps_squared = proj_eps * proj_eps; - const int N = 1000; - float u = -1.0f, du = 1.0f / N, u1 = start_u, u2 = start_u; - float ang = -1.0f; - - while (u1 > 0.0f || u2 < 1.0f) { - float n1[2], n2[2], co1[2], co2[2]; - float v1[2], v2[2]; - float ang1, ang2; - - if (u1 >= 0.0f) { - BKE_mask_point_segment_co(spline, point, u1, co1); - BKE_mask_point_normal(spline, point, u1, n1); - sub_v2_v2v2(v1, co, co1); - - if (len_squared_v2(v1) > proj_eps_squared) { - ang1 = angle_v2v2(v1, n1); - if (ang1 > M_PI / 2.0f) - ang1 = M_PI - ang1; - - if (ang < 0.0f || ang1 < ang) { - ang = ang1; - u = u1; - } - } - else { - u = u1; - break; - } - } - - if (u2 <= 1.0f) { - BKE_mask_point_segment_co(spline, point, u2, co2); - BKE_mask_point_normal(spline, point, u2, n2); - sub_v2_v2v2(v2, co, co2); - - if (len_squared_v2(v2) > proj_eps_squared) { - ang2 = angle_v2v2(v2, n2); - if (ang2 > M_PI / 2.0f) - ang2 = M_PI - ang2; - - if (ang2 < ang) { - ang = ang2; - u = u2; - } - } - else { - u = u2; - break; - } - } - - u1 -= du; - u2 += du; - } - - return u; -} - MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float normal_co[2], int threshold, MaskLayer **masklay_r, MaskSpline **spline_r, int *is_handle_r, float *score) @@ -314,123 +252,6 @@ int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], in return FALSE; } -static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_co[2], int threshold, int feather, - MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, - float *u_r, float tangent[2]) -{ - MaskLayer *masklay, *point_masklay; - MaskSpline *point_spline; - MaskSplinePoint *point = NULL; - float dist, co[2]; - int width, height; - float u; - float scalex, scaley, aspx, aspy; - - ED_mask_size(C, &width, &height); - ED_mask_aspect(C, &aspx, &aspy); - ED_mask_pixelspace_factor(C, &scalex, &scaley); - - co[0] = normal_co[0] * scalex; - co[1] = normal_co[1] * scaley; - - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskSpline *spline; - - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { - continue; - } - - for (spline = masklay->splines.first; spline; spline = spline->next) { - int i; - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *cur_point = &spline->points[i]; - float *diff_points; - int tot_diff_point; - - diff_points = BKE_mask_point_segment_diff_with_resolution(spline, cur_point, width, height, - &tot_diff_point); - - if (diff_points) { - int i, tot_feather_point, tot_point; - float *feather_points = NULL, *points; - - if (feather) { - feather_points = BKE_mask_point_segment_feather_diff_with_resolution(spline, cur_point, - width, height, - &tot_feather_point); - - points = feather_points; - tot_point = tot_feather_point; - } - else { - points = diff_points; - tot_point = tot_diff_point; - } - - for (i = 0; i < tot_point - 1; i++) { - float cur_dist, a[2], b[2]; - - a[0] = points[2 * i] * scalex; - a[1] = points[2 * i + 1] * scaley; - - b[0] = points[2 * i + 2] * scalex; - b[1] = points[2 * i + 3] * scaley; - - cur_dist = dist_to_line_segment_v2(co, a, b); - - if (point == NULL || cur_dist < dist) { - if (tangent) - sub_v2_v2v2(tangent, &diff_points[2 * i + 2], &diff_points[2 * i]); - - point_masklay = masklay; - point_spline = spline; - point = cur_point; - dist = cur_dist; - u = (float)i / tot_point; - - } - } - - if (feather_points) - MEM_freeN(feather_points); - - MEM_freeN(diff_points); - } - } - } - } - - if (point && dist < threshold) { - if (masklay_r) - *masklay_r = point_masklay; - - if (spline_r) - *spline_r = point_spline; - - if (point_r) - *point_r = point; - - if (u_r) { - u = projection_on_spline(point_spline, point, u, normal_co); - - *u_r = u; - } - - return TRUE; - } - - if (masklay_r) - *masklay_r = NULL; - - if (spline_r) - *spline_r = NULL; - - if (point_r) - *point_r = NULL; - - return FALSE; -} /******************** create new mask *********************/ @@ -829,7 +650,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) add_v2_v2v2(offco, data->feather, dco); if (data->uw) { - float u = projection_on_spline(data->spline, data->point, data->uw->u, offco); + float u = BKE_mask_spline_project_co(data->spline, data->point, data->uw->u, offco); if (u > 0.0f && u < 1.0f) { data->uw->u = u; @@ -943,535 +764,6 @@ void MASK_OT_slide_point(wmOperatorType *ot) RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide slide feather instead of vertex"); } -/******************** add vertex *********************/ - -static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, - const float point_co[2], const float tangent[2], const float u, - MaskSplinePoint *reference_point, const short reference_adjacent) -{ - MaskSplinePoint *prev_point = NULL; - MaskSplinePoint *next_point = NULL; - BezTriple *bezt; - int width, height; - float co[3]; - const float len = 20.0; /* default length of handle in pixel space */ - - copy_v2_v2(co, point_co); - co[2] = 0.0f; - - ED_mask_size(C, &width, &height); - - /* point coordinate */ - bezt = &new_point->bezt; - - bezt->h1 = bezt->h2 = HD_ALIGN; - - if (reference_point) { - bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1); - } - else if (reference_adjacent) { - if (spline->tot_point != 1) { - int index = (int)(new_point - spline->points); - prev_point = &spline->points[(index - 1) % spline->tot_point]; - next_point = &spline->points[(index + 1) % spline->tot_point]; - - bezt->h1 = bezt->h2 = MAX2(prev_point->bezt.h2, next_point->bezt.h1); - - /* note, we may want to copy other attributes later, radius? pressure? color? */ - } - } - - copy_v3_v3(bezt->vec[0], co); - copy_v3_v3(bezt->vec[1], co); - copy_v3_v3(bezt->vec[2], co); - - /* initial offset for handles */ - if (spline->tot_point == 1) { - /* first point of splien is aligned horizontally */ - bezt->vec[0][0] -= len / width; - bezt->vec[2][0] += len / width; - } - else if (tangent) { - float vec[2]; - - copy_v2_v2(vec, tangent); - - vec[0] *= width; - vec[1] *= height; - - mul_v2_fl(vec, len / len_v2(vec)); - - vec[0] /= width; - vec[1] /= height; - - sub_v2_v2(bezt->vec[0], vec); - add_v2_v2(bezt->vec[2], vec); - - if (reference_adjacent) { - BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); - } - } - else { - - /* calculating auto handles works much nicer */ -#if 0 - /* next points are aligning in the direction of previous/next point */ - MaskSplinePoint *point; - float v1[2], v2[2], vec[2]; - float dir = 1.0f; - - if (new_point == spline->points) { - point = new_point + 1; - dir = -1.0f; - } - else - point = new_point - 1; - - if (spline->tot_point < 3) { - v1[0] = point->bezt.vec[1][0] * width; - v1[1] = point->bezt.vec[1][1] * height; - - v2[0] = new_point->bezt.vec[1][0] * width; - v2[1] = new_point->bezt.vec[1][1] * height; - } - else { - if (new_point == spline->points) { - v1[0] = spline->points[1].bezt.vec[1][0] * width; - v1[1] = spline->points[1].bezt.vec[1][1] * height; - - v2[0] = spline->points[spline->tot_point - 1].bezt.vec[1][0] * width; - v2[1] = spline->points[spline->tot_point - 1].bezt.vec[1][1] * height; - } - else { - v1[0] = spline->points[0].bezt.vec[1][0] * width; - v1[1] = spline->points[0].bezt.vec[1][1] * height; - - v2[0] = spline->points[spline->tot_point - 2].bezt.vec[1][0] * width; - v2[1] = spline->points[spline->tot_point - 2].bezt.vec[1][1] * height; - } - } - - sub_v2_v2v2(vec, v1, v2); - mul_v2_fl(vec, len * dir / len_v2(vec)); - - vec[0] /= width; - vec[1] /= height; - - add_v2_v2(bezt->vec[0], vec); - sub_v2_v2(bezt->vec[2], vec); -#else - BKE_mask_calc_handle_point_auto(mask, spline, new_point, TRUE); - BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); - -#endif - } - - BKE_mask_parent_init(&new_point->parent); - - /* select new point */ - MASKPOINT_SEL_ALL(new_point); - ED_mask_select_flush_all(mask); -} - -/* **** add subdivide vertex **** */ - -static void mask_spline_add_point_at_index(MaskSpline *spline, int point_index) -{ - MaskSplinePoint *new_point_array; - - new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); - - memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * (point_index + 1)); - memcpy(new_point_array + point_index + 2, spline->points + point_index + 1, - sizeof(MaskSplinePoint) * (spline->tot_point - point_index - 1)); - - MEM_freeN(spline->points); - spline->points = new_point_array; - spline->tot_point++; -} - -static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) -{ - MaskLayer *masklay; - MaskSpline *spline; - MaskSplinePoint *point = NULL; - const float threshold = 9; - float tangent[2]; - float u; - - if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, &u, tangent)) { - MaskSplinePoint *new_point; - int point_index = point - spline->points; - - ED_mask_select_toggle_all(mask, SEL_DESELECT); - - mask_spline_add_point_at_index(spline, point_index); - - new_point = &spline->points[point_index + 1]; - - setup_vertex_point(C, mask, spline, new_point, co, tangent, u, NULL, TRUE); - - /* TODO - we could pass the spline! */ - BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index + 1, TRUE, TRUE); - - masklay->act_point = new_point; - - WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - - return TRUE; - } - - return FALSE; -} - -/* **** add extrude vertex **** */ - -static void finSelectedSplinePoint(MaskLayer *masklay, MaskSpline **spline, MaskSplinePoint **point, short check_active) -{ - MaskSpline *cur_spline = masklay->splines.first; - - *spline = NULL; - *point = NULL; - - if (check_active) { - if (masklay->act_spline && masklay->act_point) { - *spline = masklay->act_spline; - *point = masklay->act_point; - return; - } - } - - while (cur_spline) { - int i; - - for (i = 0; i < cur_spline->tot_point; i++) { - MaskSplinePoint *cur_point = &cur_spline->points[i]; - - if (MASKPOINT_ISSEL_ANY(cur_point)) { - if (*spline != NULL && *spline != cur_spline) { - *spline = NULL; - *point = NULL; - return; - } - else if (*point) { - *point = NULL; - } - else { - *spline = cur_spline; - *point = cur_point; - } - } - } - - cur_spline = cur_spline->next; - } -} - -static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2]) -{ - MaskSpline *spline; - MaskSplinePoint *point; - MaskSplinePoint *new_point = NULL, *ref_point = NULL; - - /* check on which side we want to add the point */ - int point_index; - float tangent_point[2]; - float tangent_co[2]; - int do_cyclic_correct = FALSE; - int do_recalc_src = FALSE; /* when extruding from endpoints only */ - int do_prev; /* use prev point rather then next?? */ - - ED_mask_select_toggle_all(mask, SEL_DESELECT); - - if (!masklay) { - return FALSE; - } - else { - finSelectedSplinePoint(masklay, &spline, &point, TRUE); - } - - point_index = (point - spline->points); - - MASKPOINT_DESEL_ALL(point); - - if ((spline->flag & MASK_SPLINE_CYCLIC) || - (point_index > 0 && point_index != spline->tot_point - 1)) - { - BKE_mask_calc_tangent_polyline(mask, spline, point, tangent_point); - sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]); - - if (dot_v2v2(tangent_point, tangent_co) < 0.0f) { - do_prev = TRUE; - } - else { - do_prev = FALSE; - } - } - else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == 0)) { - do_prev = TRUE; - do_recalc_src = TRUE; - } - else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == spline->tot_point - 1)) { - do_prev = FALSE; - do_recalc_src = TRUE; - } - else { - /* should never get here */ - BLI_assert(0); - } - - /* use the point before the active one */ - if (do_prev) { - point_index--; - if (point_index < 0) { - point_index += spline->tot_point; /* wrap index */ - if ((spline->flag & MASK_SPLINE_CYCLIC) == 0) { - do_cyclic_correct = TRUE; - point_index = 0; - } - } - } - -// print_v2("", tangent_point); -// printf("%d\n", point_index); - - mask_spline_add_point_at_index(spline, point_index); - - if (do_cyclic_correct) { - ref_point = &spline->points[point_index + 1]; - new_point = &spline->points[point_index]; - *ref_point = *new_point; - memset(new_point, 0, sizeof(*new_point)); - } - else { - ref_point = &spline->points[point_index]; - new_point = &spline->points[point_index + 1]; - } - - masklay->act_point = new_point; - - setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE); - - if (masklay->splines_shapes.first) { - point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); - BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, TRUE, TRUE); - } - - if (do_recalc_src) { - /* TODO, update keyframes in time */ - BKE_mask_calc_handle_point_auto(mask, spline, ref_point, FALSE); - } - - WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - - return TRUE; -} - -static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2]) -{ - MaskSpline *spline; - MaskSplinePoint *point; - MaskSplinePoint *new_point = NULL, *ref_point = NULL; - - ED_mask_select_toggle_all(mask, SEL_DESELECT); - - if (!masklay) { - /* if there's no masklay currently operationg on, create new one */ - masklay = BKE_mask_layer_new(mask, ""); - mask->masklay_act = mask->masklay_tot - 1; - spline = NULL; - point = NULL; - } - else { - finSelectedSplinePoint(masklay, &spline, &point, TRUE); - } - - if (!spline) { - /* no selected splines in active masklay, create new spline */ - spline = BKE_mask_spline_add(masklay); - } - - masklay->act_spline = spline; - new_point = spline->points; - - masklay->act_point = new_point; - - setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE); - - { - int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); - BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, TRUE, TRUE); - } - - WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - - return TRUE; -} - -static int add_vertex_exec(bContext *C, wmOperator *op) -{ - Mask *mask = CTX_data_edit_mask(C); - MaskLayer *masklay; - - float co[2]; - - masklay = BKE_mask_layer_active(mask); - - if (masklay && masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { - masklay = NULL; - } - - RNA_float_get_array(op->ptr, "location", co); - - if (masklay && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) { - - /* cheap trick - double click for cyclic */ - MaskSpline *spline = masklay->act_spline; - MaskSplinePoint *point = masklay->act_point; - - int is_sta = (point == spline->points); - int is_end = (point == &spline->points[spline->tot_point - 1]); - - /* then check are we overlapping the mouse */ - if ((is_sta || is_end) && equals_v2v2(co, point->bezt.vec[1])) { - if (spline->flag & MASK_SPLINE_CYCLIC) { - /* nothing to do */ - return OPERATOR_CANCELLED; - } - else { - /* recalc the connecting point as well to make a nice even curve */ - MaskSplinePoint *point_other = is_end ? spline->points : &spline->points[spline->tot_point - 1]; - spline->flag |= MASK_SPLINE_CYCLIC; - - /* TODO, update keyframes in time */ - BKE_mask_calc_handle_point_auto(mask, spline, point, FALSE); - BKE_mask_calc_handle_point_auto(mask, spline, point_other, FALSE); - - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); - - WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - return OPERATOR_FINISHED; - } - } - - if (!add_vertex_subdivide(C, mask, co)) { - if (!add_vertex_extrude(C, mask, masklay, co)) { - return OPERATOR_CANCELLED; - } - } - } - else { - if (!add_vertex_subdivide(C, mask, co)) { - if (!add_vertex_new(C, mask, masklay, co)) { - return OPERATOR_CANCELLED; - } - } - } - - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); - - return OPERATOR_FINISHED; -} - -static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - float co[2]; - - ED_mask_mouse_pos(C, event, co); - - RNA_float_set_array(op->ptr, "location", co); - - return add_vertex_exec(C, op); -} - -void MASK_OT_add_vertex(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Add Vertex"; - ot->description = "Add vertex to active spline"; - ot->idname = "MASK_OT_add_vertex"; - - /* api callbacks */ - ot->exec = add_vertex_exec; - ot->invoke = add_vertex_invoke; - ot->poll = ED_maskediting_mask_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, - "Location", "Location of vertex in normalized space", -1.0f, 1.0f); -} - -/******************** add feather vertex *********************/ - -static int add_feather_vertex_exec(bContext *C, wmOperator *op) -{ - Mask *mask = CTX_data_edit_mask(C); - MaskLayer *masklay; - MaskSpline *spline; - MaskSplinePoint *point = NULL; - const float threshold = 9; - float co[2], u; - - RNA_float_get_array(op->ptr, "location", co); - - point = ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL); - if (point) - return OPERATOR_FINISHED; - - if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &masklay, &spline, &point, &u, NULL)) { - Scene *scene = CTX_data_scene(C); - float w = BKE_mask_point_weight(spline, point, u); - - BKE_mask_point_add_uw(point, u, w); - - BKE_mask_update_display(mask, scene->r.cfra); - - WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - - DAG_id_tag_update(&mask->id, 0); - - return OPERATOR_FINISHED; - } - - return OPERATOR_CANCELLED; -} - -static int add_feather_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - float co[2]; - - ED_mask_mouse_pos(C, event, co); - - RNA_float_set_array(op->ptr, "location", co); - - return add_feather_vertex_exec(C, op); -} - -void MASK_OT_add_feather_vertex(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Add feather Vertex"; - ot->description = "Add vertex to feather"; - ot->idname = "MASK_OT_add_feather_vertex"; - - /* api callbacks */ - ot->exec = add_feather_vertex_exec; - ot->invoke = add_feather_vertex_invoke; - ot->poll = ED_maskediting_mask_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, - "Location", "Location of vertex in normalized space", -1.0f, 1.0f); -} - /******************** toggle cyclic *********************/ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) From f8266d5a4b0d76faad90df8a285c1a070ecd8e9e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 14:35:45 +0000 Subject: [PATCH 167/183] dont extrude from active-unselected mask-spline verts. --- source/blender/editors/mask/mask_add.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 62675635b7b..c2c2ebbfe42 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -317,7 +317,7 @@ static void finSelectedSplinePoint(MaskLayer *masklay, MaskSpline **spline, Mask *point = NULL; if (check_active) { - if (masklay->act_spline && masklay->act_point) { + if (masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) { *spline = masklay->act_spline; *point = masklay->act_point; return; @@ -415,8 +415,6 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const int do_recalc_src = FALSE; /* when extruding from endpoints only */ int do_prev; /* use prev point rather then next?? */ - ED_mask_select_toggle_all(mask, SEL_DESELECT); - if (!masklay) { return FALSE; } @@ -424,6 +422,8 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const finSelectedSplinePoint(masklay, &spline, &point, TRUE); } + ED_mask_select_toggle_all(mask, SEL_DESELECT); + point_index = (point - spline->points); MASKPOINT_DESEL_ALL(point); @@ -507,8 +507,6 @@ static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const flo MaskSplinePoint *point; MaskSplinePoint *new_point = NULL, *ref_point = NULL; - ED_mask_select_toggle_all(mask, SEL_DESELECT); - if (!masklay) { /* if there's no masklay currently operationg on, create new one */ masklay = BKE_mask_layer_new(mask, ""); @@ -520,6 +518,8 @@ static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const flo finSelectedSplinePoint(masklay, &spline, &point, TRUE); } + ED_mask_select_toggle_all(mask, SEL_DESELECT); + if (!spline) { /* no selected splines in active masklay, create new spline */ spline = BKE_mask_spline_add(masklay); From 276701502a6a55be8e447a728914406150e7b7c0 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Fri, 8 Jun 2012 17:42:17 +0000 Subject: [PATCH 168/183] Make planar tracking much faster. - This makes planar tracking around 2-3x or more faster than before, by rearranging how the sampling is done. Previously, the source patch was sampled repeatedly on every optimizer iteration; this was done for implementation speed, but was wasteful in computation. - This also contains some additions to Ceres to help deailing with mixed numeric / automatic differentation. In particular, there is now a "Chain::Rule" operator that facilitates calling a function that takes Jet arguments, yet does numeric derivatives internally. This is used to mix the numeric differentation of the images with the warp parameters, passed as jets by Ceres to the warp functor. There is also a new "JetOps" object for doing operations on types which may or may not be jets, such as scaling the derivative part only, or extracting the scalar part of a jet. The Ceres patches are aimed at upstream. - A new function for sampling a patch is now part of the track_region.h API; this will get used to make the preview widget properly show what is getting tracked. Currently the preview widget does not handle perspective tracks. Known issues: This patch introduces a bug such that the "Minimum Correlation" flag does not work; if it is enabled, tracking aborts immediately. The workaround for now is to disable the correlation checking, and examine your tracks carefully. A fix will get added shortly. --- extern/libmv/libmv/image/sample.h | 29 +- extern/libmv/libmv/tracking/track_region.cc | 297 ++++++++++-------- extern/libmv/libmv/tracking/track_region.h | 10 + .../third_party/ceres/include/ceres/jet.h | 84 +++++ 4 files changed, 286 insertions(+), 134 deletions(-) diff --git a/extern/libmv/libmv/image/sample.h b/extern/libmv/libmv/image/sample.h index e842747e6d4..7bcbe5b0401 100644 --- a/extern/libmv/libmv/image/sample.h +++ b/extern/libmv/libmv/image/sample.h @@ -37,15 +37,15 @@ inline T SampleNearest(const Array3D &image, static inline void LinearInitAxis(float fx, int width, int *x1, int *x2, float *dx1, float *dx2) { - const int ix = int(fx); + const int ix = static_cast(fx); if (ix < 0) { *x1 = 0; *x2 = 0; *dx1 = 1; *dx2 = 0; - } else if (ix > width-2) { - *x1 = width-1; - *x2 = width-1; + } else if (ix > width - 2) { + *x1 = width - 1; + *x2 = width - 1; *dx1 = 1; *dx2 = 0; } else { @@ -74,6 +74,27 @@ inline T SampleLinear(const Array3D &image, float y, float x, int v = 0) { dy2 * ( dx1 * im21 + dx2 * im22 )); } +/// Linear interpolation, of all channels. The sample is assumed to have the +/// same size as the number of channels in image. +template +inline void SampleLinear(const Array3D &image, float y, float x, T *sample) { + int x1, y1, x2, y2; + float dx1, dy1, dx2, dy2; + + LinearInitAxis(y, image.Height(), &y1, &y2, &dy1, &dy2); + LinearInitAxis(x, image.Width(), &x1, &x2, &dx1, &dx2); + + for (int i = 0; i < image.Depth(); ++i) { + const T im11 = image(y1, x1, i); + const T im12 = image(y1, x2, i); + const T im21 = image(y2, x1, i); + const T im22 = image(y2, x2, i); + + sample[i] = T(dy1 * ( dx1 * im11 + dx2 * im12 ) + + dy2 * ( dx1 * im21 + dx2 * im22 )); + } +} + // Downsample all channels by 2. If the image has odd width or height, the last // row or column is ignored. // FIXME(MatthiasF): this implementation shouldn't be in an interface file diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index 62cc43205d0..bcfb976fc68 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -43,6 +43,10 @@ namespace libmv { +using ceres::Jet; +using ceres::JetOps; +using ceres::Chain; + TrackRegionOptions::TrackRegionOptions() : mode(TRANSLATION), minimum_correlation(0), @@ -77,70 +81,30 @@ bool AllInBounds(const FloatImage &image, return true; } -// Because C++03 doesn't support partial template specializations for -// functions, but at the same time member function specializations are not -// supported, the sample function must be inside a template-specialized class -// with a non-templated static member. - // The "AutoDiff::Sample()" function allows sampling an image at an x, y // position such that if x and y are jets, then the derivative information is // correctly propagated. - -// Empty default template. template -struct AutoDiff { - // Sample only the image when the coordinates are scalars. - static T Sample(const FloatImage &image_and_gradient, - const T &x, const T &y) { - return SampleLinear(image_and_gradient, y, x, 0); - } +static T SampleWithDerivative(const FloatImage &image_and_gradient, + const T &x, + const T &y) { + float scalar_x = JetOps::GetScalar(x); + float scalar_y = JetOps::GetScalar(y); - static void SetScalarPart(double scalar, T *value) { - *value = scalar; + // Note that sample[1] and sample[2] will be uninitialized in the scalar + // case, but that is not an issue because the Chain::Rule below will not read + // the uninitialized values. + float sample[3]; + if (JetOps::IsScalar()) { + // For the scalar case, only sample the image. + sample[0] = SampleLinear(image_and_gradient, scalar_y, scalar_x, 0); + } else { + // For the derivative case, sample the gradient as well. + SampleLinear(image_and_gradient, scalar_y, scalar_x, sample); } - static void ScaleDerivative(double scale_by, T *value) { - // For double, there is no derivative to scale. - } -}; - -// Sample the image and gradient when the coordinates are jets, applying the -// jacobian appropriately to propagate the derivatives from the coordinates. -template -struct AutoDiff > { - static ceres::Jet Sample(const FloatImage &image_and_gradient, - const ceres::Jet &x, - const ceres::Jet &y) { - // Sample the image and its derivatives in x and y. One way to think of - // this is that the image is a scalar function with a single vector - // argument, xy, of dimension 2. Call this s(xy). - const T s = SampleLinear(image_and_gradient, y.a, x.a, 0); - const T dsdx = SampleLinear(image_and_gradient, y.a, x.a, 1); - const T dsdy = SampleLinear(image_and_gradient, y.a, x.a, 2); - - // However, xy is itself a function of another variable ("z"); xy(z) = - // [x(z), y(z)]^T. What this function needs to return is "s", but with the - // derivative with respect to z attached to the jet. So combine the - // derivative part of x and y's jets to form a Jacobian matrix between x, y - // and z (i.e. dxy/dz). - Eigen::Matrix dxydz; - dxydz.row(0) = x.v.transpose(); - dxydz.row(1) = y.v.transpose(); - - // Now apply the chain rule to obtain ds/dz. Combine the derivative with - // the scalar part to obtain s with full derivative information. - ceres::Jet jet_s; - jet_s.a = s; - jet_s.v = Matrix(dsdx, dsdy) * dxydz; - return jet_s; - } - - static void SetScalarPart(double scalar, ceres::Jet *value) { - value->a = scalar; - } - static void ScaleDerivative(double scale_by, ceres::Jet *value) { - value->v *= scale_by; - } -}; + T xy[2] = { x, y }; + return Chain::Rule(sample[0], sample + 1, xy); +} template class BoundaryCheckingCallback : public ceres::IterationCallback { @@ -188,36 +152,73 @@ class WarpCostFunctor { canonical_to_image1_(canonical_to_image1), num_samples_x_(num_samples_x), num_samples_y_(num_samples_y), - warp_(warp) {} + warp_(warp), + pattern_and_gradient_(num_samples_y_, num_samples_x_, 3), + pattern_positions_(num_samples_y_, num_samples_x_, 2), + pattern_mask_(num_samples_y_, num_samples_x_, 1) { + ComputeCanonicalPatchAndNormalizer(); + } + + void ComputeCanonicalPatchAndNormalizer() { + src_mean_ = 0.0; + double num_samples = 0.0; + for (int r = 0; r < num_samples_y_; ++r) { + for (int c = 0; c < num_samples_x_; ++c) { + // Compute the position; cache it. + Vec3 image_position = canonical_to_image1_ * Vec3(c, r, 1); + image_position /= image_position(2); + pattern_positions_(r, c, 0) = image_position(0); + pattern_positions_(r, c, 1) = image_position(1); + + // Sample the pattern and gradients. + SampleLinear(image_and_gradient1_, + image_position(1), // Sample is r, c. + image_position(0), + &pattern_and_gradient_(r, c, 0)); + + // Sample sample the mask. + double mask_value = 1.0; + if (options_.image1_mask != NULL) { + SampleLinear(*options_.image1_mask, + image_position(1), + image_position(0), + &pattern_mask_(r, c, 0)); + mask_value = pattern_mask_(r, c); + } + src_mean_ += pattern_and_gradient_(r, c, 0) * mask_value; + num_samples += mask_value; + } + } + src_mean_ /= num_samples; + } template bool operator()(const T *warp_parameters, T *residuals) const { + if (options_.image1_mask != NULL) { + VLOG(2) << "Using a mask."; + } for (int i = 0; i < Warp::NUM_PARAMETERS; ++i) { VLOG(2) << "warp_parameters[" << i << "]: " << warp_parameters[i]; } - T src_mean = T(1.0); T dst_mean = T(1.0); if (options_.use_normalized_intensities) { - ComputeNormalizingCoefficients(warp_parameters, - &src_mean, - &dst_mean); + ComputeNormalizingCoefficient(warp_parameters, + &dst_mean); } int cursor = 0; for (int r = 0; r < num_samples_y_; ++r) { for (int c = 0; c < num_samples_x_; ++c) { - // Compute the location of the source pixel (via homography). - Vec3 image1_position = canonical_to_image1_ * Vec3(c, r, 1); - image1_position /= image1_position(2); - + // Use the pre-computed image1 position. + Vec2 image1_position(pattern_positions_(r, c, 0), + pattern_positions_(r, c, 1)); + // Sample the mask early; if it's zero, this pixel has no effect. This // allows early bailout from the expensive sampling that happens below. double mask_value = 1.0; if (options_.image1_mask != NULL) { - mask_value = AutoDiff::Sample(*options_.image1_mask, - image1_position[0], - image1_position[1]); + mask_value = pattern_mask_(r, c); if (mask_value == 0.0) { residuals[cursor++] = T(0.0); continue; @@ -233,54 +234,61 @@ class WarpCostFunctor { &image2_position[1]); // Sample the destination, propagating derivatives. - T dst_sample = AutoDiff::Sample(image_and_gradient2_, - image2_position[0], - image2_position[1]); + T dst_sample = SampleWithDerivative(image_and_gradient2_, + image2_position[0], + image2_position[1]); // Sample the source. This is made complicated by ESM mode. T src_sample; - if (options_.use_esm) { + if (0 && options_.use_esm && !JetOps::IsScalar()) { // In ESM mode, the derivative of the source is also taken into // account. This changes the linearization in a way that causes // better convergence. Copy the derivative of the warp parameters // onto the jets for the image1 position. This is the ESM hack. - T image1_position_x = image2_position[0]; - T image1_position_y = image2_position[1]; - AutoDiff::SetScalarPart(image1_position[0], &image1_position_x); - AutoDiff::SetScalarPart(image1_position[1], &image1_position_y); - src_sample = AutoDiff::Sample(image_and_gradient1_, - image1_position_x, - image1_position_y); + T image1_position_jet[2] = { + image2_position[0], // Order is x, y. This matches the + image2_position[1] // derivative order in the patch. + }; + JetOps::SetScalar(image1_position[0], image1_position_jet + 0); + JetOps::SetScalar(image1_position[1], image1_position_jet + 1); + + // Now that the image1 positions have the jets applied from the + // image2 position (the ESM hack), chain the image gradients to + // obtain a sample with the derivative with respect to the warp + // parameters attached. + src_sample = Chain::Rule(pattern_and_gradient_(r, c), + &pattern_and_gradient_(r, c, 1), + image1_position_jet); // The jacobians for these should be averaged. Due to the subtraction // below, flip the sign of the src derivative so that the effect // after subtraction of the jets is that they are averaged. - AutoDiff::ScaleDerivative(-0.5, &src_sample); - AutoDiff::ScaleDerivative(0.5, &dst_sample); + JetOps::ScaleDerivative(-0.5, &src_sample); + JetOps::ScaleDerivative(0.5, &dst_sample); } else { // This is the traditional, forward-mode KLT solution. - src_sample = T(AutoDiff::Sample(image_and_gradient1_, - image1_position[0], - image1_position[1])); + src_sample = T(pattern_and_gradient_(r, c)); } + //LG << "src_sample: " << src_sample; + // Normalize the samples by the mean values of each signal. The typical // light model assumes multiplicative intensity changes with changing // light, so this is a reasonable choice. Note that dst_mean has // derivative information attached thanks to autodiff. if (options_.use_normalized_intensities) { - src_sample /= src_mean; + src_sample /= T(src_mean_); dst_sample /= dst_mean; } + //LG << "dst_sample: " << dst_sample; + // The difference is the error. T error = src_sample - dst_sample; // Weight the error by the mask, if one is present. if (options_.image1_mask != NULL) { - error *= T(AutoDiff::Sample(*options_.image1_mask, - image1_position[0], - image1_position[1])); + error *= T(mask_value); } residuals[cursor++] = error; } @@ -290,26 +298,22 @@ class WarpCostFunctor { // For normalized matching, the average and template - void ComputeNormalizingCoefficients(const T *warp_parameters, - T *src_mean, - T *dst_mean) const { + void ComputeNormalizingCoefficient(const T *warp_parameters, + T *dst_mean) const { - *src_mean = T(0.0); *dst_mean = T(0.0); double num_samples = 0.0; for (int r = 0; r < num_samples_y_; ++r) { for (int c = 0; c < num_samples_x_; ++c) { - // Compute the location of the source pixel (via homography). - Vec3 image1_position = canonical_to_image1_ * Vec3(c, r, 1); - image1_position /= image1_position(2); + // Use the pre-computed image1 position. + Vec2 image1_position(pattern_positions_(r, c, 0), + pattern_positions_(r, c, 1)); // Sample the mask early; if it's zero, this pixel has no effect. This // allows early bailout from the expensive sampling that happens below. double mask_value = 1.0; if (options_.image1_mask != NULL) { - mask_value = AutoDiff::Sample(*options_.image1_mask, - image1_position[0], - image1_position[1]); + mask_value = pattern_mask_(r, c); if (mask_value == 0.0) { continue; } @@ -328,31 +332,20 @@ class WarpCostFunctor { // TODO(keir): This accumulation can, surprisingly, be done as a // pre-pass by using integral images. This is complicated by the need // to store the jets in the integral image, but it is possible. - T dst_sample = AutoDiff::Sample(image_and_gradient2_, - image2_position[0], - image2_position[1]); - - // Sample the source. - // TODO(keir): There is no reason to do this inside the loop; - // precompute this and reuse it. - T src_sample = T(AutoDiff::Sample(image_and_gradient1_, - image1_position[0], - image1_position[1])); + T dst_sample = SampleWithDerivative(image_and_gradient2_, + image2_position[0], + image2_position[1]); // Weight the sample by the mask, if one is present. if (options_.image1_mask != NULL) { - src_sample *= T(mask_value); dst_sample *= T(mask_value); } - *src_mean += src_sample; *dst_mean += dst_sample; num_samples += mask_value; } } - *src_mean /= T(num_samples); *dst_mean /= T(num_samples); - LG << "Normalization for src:" << *src_mean; LG << "Normalization for dst:" << *dst_mean; } @@ -369,16 +362,23 @@ class WarpCostFunctor { double sX = 0, sY = 0, sXX = 0, sYY = 0, sXY = 0; // Due to masking, it's important to account for fractional samples. - // Samples with a 50% mask get counted as a half sample. + // For example, samples with a 50% mask are counted as a half sample. double num_samples = 0; for (int r = 0; r < num_samples_y_; ++r) { for (int c = 0; c < num_samples_x_; ++c) { - // Compute the location of the source pixel (via homography). - // TODO(keir): Cache these projections. - Vec3 image1_position = canonical_to_image1_ * Vec3(c, r, 1); - image1_position /= image1_position(2); + // Use the pre-computed image1 position. + Vec2 image1_position(pattern_positions_(r, c, 0), + pattern_positions_(r, c, 1)); + double mask_value = 1.0; + if (options_.image1_mask != NULL) { + mask_value = pattern_mask_(r, c); + if (mask_value == 0.0) { + continue; + } + } + // Compute the location of the destination pixel. double image2_position[2]; warp_.Forward(warp_parameters, @@ -387,19 +387,13 @@ class WarpCostFunctor { &image2_position[0], &image2_position[1]); - double x = AutoDiff::Sample(image_and_gradient2_, - image2_position[0], - image2_position[1]); - - double y = AutoDiff::Sample(image_and_gradient1_, - image1_position[0], - image1_position[1]); + double x = pattern_and_gradient_(r, c); + double y = SampleLinear(image_and_gradient2_, + image2_position[0], + image2_position[1]); // Weight the signals by the mask, if one is present. if (options_.image1_mask != NULL) { - double mask_value = AutoDiff::Sample(*options_.image1_mask, - image1_position[0], - image1_position[1]); x *= mask_value; y *= mask_value; num_samples += mask_value; @@ -439,6 +433,15 @@ class WarpCostFunctor { int num_samples_x_; int num_samples_y_; const Warp &warp_; + double src_mean_; + FloatImage pattern_and_gradient_; + + // This contains the position from where the cached pattern samples were + // taken from. This is also used to warp from src to dest without going from + // canonical pixels to src first. + FloatImage pattern_positions_; + + FloatImage pattern_mask_; }; // Compute the warp from rectangular coordinates, where one corner is the @@ -1073,6 +1076,9 @@ void TemplatedTrackRegion(const FloatImage &image1, << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", " << (y2[i] - y1[i]) << ")."; } + if (options.use_normalized_intensities) { + LG << "Using normalized intensities."; + } // Bail early if the points are already outside. if (!AllInBounds(image1, x1, y1)) { @@ -1232,7 +1238,6 @@ void TrackRegion(const FloatImage &image1, result); \ return; \ } - HANDLE_MODE(TRANSLATION, TranslationWarp); HANDLE_MODE(TRANSLATION_SCALE, TranslationScaleWarp); HANDLE_MODE(TRANSLATION_ROTATION, TranslationRotationWarp); @@ -1242,4 +1247,36 @@ void TrackRegion(const FloatImage &image1, #undef HANDLE_MODE } +bool SamplePlanarPatch(const FloatImage &image, + const double *xs, const double *ys, + int num_samples_x, int num_samples_y, + FloatImage *patch) { + // Bail early if the points are outside the image. + if (!AllInBounds(image, xs, ys)) { + LG << "Can't sample patch: out of bounds."; + return false; + } + + // Make the patch have the appropriate size, and match the depth of image. + patch->Resize(num_samples_y, num_samples_x, image.Depth()); + + // Compute the warp from rectangular coordinates. + Mat3 canonical_homography = ComputeCanonicalHomography(xs, ys, + num_samples_x, + num_samples_y); + + // Walk over the coordinates in the canonical space, sampling from the image + // in the original space and copying the result into the patch. + for (int r = 0; r < num_samples_y; ++r) { + for (int c = 0; c < num_samples_x; ++c) { + Vec3 image_position = canonical_homography * Vec3(c, r, 1); + image_position /= image_position(2); + SampleLinear(image, image_position(1), + image_position(0), + &(*patch)(r, c, 0)); + } + } + return true; +} + } // namespace libmv diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h index 4a1427a6b9f..ca21090e7c0 100644 --- a/extern/libmv/libmv/tracking/track_region.h +++ b/extern/libmv/libmv/tracking/track_region.h @@ -113,6 +113,16 @@ void TrackRegion(const FloatImage &image1, double *x2, double *y2, TrackRegionResult *result); +// Sample a "canonical" version of the passed planar patch, using bilinear +// sampling. The passed corners must be within the image, possibly with a small +// amount of slop, perhaps 2 pixels, around the edges (so e.g. a corner of the +// patch cannot lie directly on the edge of the image). Four corners are always +// required. All channels are interpolated. +bool SamplePlanarPatch(const FloatImage &image, + const double *xs, const double *ys, + int num_samples_x, int num_samples_y, + FloatImage *patch); + } // namespace libmv #endif // LIBMV_TRACKING_TRACK_REGION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/jet.h b/extern/libmv/third_party/ceres/include/ceres/jet.h index f73c6988951..264861735ed 100644 --- a/extern/libmv/third_party/ceres/include/ceres/jet.h +++ b/extern/libmv/third_party/ceres/include/ceres/jet.h @@ -199,6 +199,18 @@ struct Jet { v[k] = T(1.0); } + /* + + // Construct from an array where the first element is the scalar. + // This is templated to support converting from other data types. + template + Jet(const D* scalar_and_derivatives) { + a = T(scalar_and_derivatives[0]); + v = Eigen::Map >( + scalar_and_derivatives + 1, N).cast(); + } + */ + // Compound operators Jet& operator+=(const Jet &y) { *this = *this + y; @@ -638,6 +650,78 @@ inline std::ostream &operator<<(std::ostream &s, const Jet& z) { return s << "[" << z.a << " ; " << z.v.transpose() << "]"; } +// A jet traits class to make it easier to work with mixed auto / numeric diff. +template +struct JetOps { + static bool IsScalar() { + return true; + } + static T GetScalar(const T& t) { + return t; + } + static void SetScalar(const T& scalar, T* t) { + *t = scalar; + } + static void ScaleDerivative(double scale_by, T *value) { + // For double, there is no derivative to scale. + } +}; + +template +struct JetOps > { + static bool IsScalar() { + return false; + } + static T GetScalar(const Jet& t) { + return t.a; + } + static void SetScalar(const T& scalar, Jet* t) { + t->a = scalar; + } + static void ScaleDerivative(double scale_by, Jet *value) { + value->v *= scale_by; + } +}; + +template +struct Chain { + static ArgumentType Rule(const FunctionType &f, + const FunctionType dfdx[kNumArgs], + const ArgumentType x[kNumArgs]) { + // In the default case of scalars, there's nothing to do since there are no + // derivatives to propagate. + return f; + } +}; + +// XXX Add documentation here! +template +struct Chain > { + static Jet Rule(const FunctionType &f, + const FunctionType dfdx[kNumArgs], + const Jet x[kNumArgs]) { + // x is itself a function of another variable ("z"); what this function + // needs to return is "f", but with the derivative with respect to z + // attached to the jet. So combine the derivative part of x's jets to form + // a Jacobian matrix between x and z (i.e. dx/dz). + Eigen::Matrix dxdz; + for (int i = 0; i < kNumArgs; ++i) { + dxdz.row(i) = x[i].v.transpose(); + } + + // Map the input gradient dfdx into an Eigen row vector. + Eigen::Map > + vector_dfdx(dfdx, 1, kNumArgs); + + // Now apply the chain rule to obtain df/dz. Combine the derivative with + // the scalar part to obtain f with full derivative information. + Jet jet_f; + jet_f.a = f; + jet_f.v = vector_dfdx.template cast() * dxdz; // Also known as dfdz. + return jet_f; + } +}; + } // namespace ceres namespace Eigen { From f9be7fca1747218323cc53a52842374229cdff4a Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Sat, 9 Jun 2012 06:55:21 +0000 Subject: [PATCH 169/183] Planar tracker polish. - Fixes the correlation checking code that was broken in the previous commit. The bug was a transpose error. - Fixes a memory leak of the warp functor, found by Sameer. - Various cleanups done at Sameer's suggestion. Thanks to Sameer Agarwal for a code review. --- extern/libmv/libmv/image/sample.h | 45 +++++++------ extern/libmv/libmv/tracking/track_region.cc | 70 +++++++++++---------- extern/libmv/libmv/tracking/track_region.h | 8 +-- 3 files changed, 61 insertions(+), 62 deletions(-) diff --git a/extern/libmv/libmv/image/sample.h b/extern/libmv/libmv/image/sample.h index 7bcbe5b0401..04a5748ea44 100644 --- a/extern/libmv/libmv/image/sample.h +++ b/extern/libmv/libmv/image/sample.h @@ -34,25 +34,22 @@ inline T SampleNearest(const Array3D &image, return image(i, j, v); } -static inline void LinearInitAxis(float fx, int width, - int *x1, int *x2, - float *dx1, float *dx2) { - const int ix = static_cast(fx); +inline void LinearInitAxis(float x, int size, + int *x1, int *x2, + float *dx) { + const int ix = static_cast(x); if (ix < 0) { *x1 = 0; *x2 = 0; - *dx1 = 1; - *dx2 = 0; - } else if (ix > width - 2) { - *x1 = width - 1; - *x2 = width - 1; - *dx1 = 1; - *dx2 = 0; + *dx = 1.0; + } else if (ix > size - 2) { + *x1 = size - 1; + *x2 = size - 1; + *dx = 1.0; } else { *x1 = ix; - *x2 = *x1 + 1; - *dx1 = *x2 - fx; - *dx2 = 1 - *dx1; + *x2 = ix + 1; + *dx = *x2 - x; } } @@ -60,18 +57,18 @@ static inline void LinearInitAxis(float fx, int width, template inline T SampleLinear(const Array3D &image, float y, float x, int v = 0) { int x1, y1, x2, y2; - float dx1, dy1, dx2, dy2; + float dx, dy; - LinearInitAxis(y, image.Height(), &y1, &y2, &dy1, &dy2); - LinearInitAxis(x, image.Width(), &x1, &x2, &dx1, &dx2); + LinearInitAxis(y, image.Height(), &y1, &y2, &dy); + LinearInitAxis(x, image.Width(), &x1, &x2, &dx); const T im11 = image(y1, x1, v); const T im12 = image(y1, x2, v); const T im21 = image(y2, x1, v); const T im22 = image(y2, x2, v); - return T(dy1 * ( dx1 * im11 + dx2 * im12 ) + - dy2 * ( dx1 * im21 + dx2 * im22 )); + return T( dy * ( dx * im11 + (1.0 - dx) * im12 ) + + (1 - dy) * ( dx * im21 + (1.0 - dx) * im22 )); } /// Linear interpolation, of all channels. The sample is assumed to have the @@ -79,10 +76,10 @@ inline T SampleLinear(const Array3D &image, float y, float x, int v = 0) { template inline void SampleLinear(const Array3D &image, float y, float x, T *sample) { int x1, y1, x2, y2; - float dx1, dy1, dx2, dy2; + float dx, dy; - LinearInitAxis(y, image.Height(), &y1, &y2, &dy1, &dy2); - LinearInitAxis(x, image.Width(), &x1, &x2, &dx1, &dx2); + LinearInitAxis(y, image.Height(), &y1, &y2, &dy); + LinearInitAxis(x, image.Width(), &x1, &x2, &dx); for (int i = 0; i < image.Depth(); ++i) { const T im11 = image(y1, x1, i); @@ -90,8 +87,8 @@ inline void SampleLinear(const Array3D &image, float y, float x, T *sample) { const T im21 = image(y2, x1, i); const T im22 = image(y2, x2, i); - sample[i] = T(dy1 * ( dx1 * im11 + dx2 * im12 ) + - dy2 * ( dx1 * im21 + dx2 * im22 )); + sample[i] = T( dy * ( dx * im11 + (1.0 - dx) * im12 ) + + (1 - dy) * ( dx * im21 + (1.0 - dx) * im22 )); } } diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index bcfb976fc68..b9e4f883e78 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -81,9 +81,9 @@ bool AllInBounds(const FloatImage &image, return true; } -// The "AutoDiff::Sample()" function allows sampling an image at an x, y -// position such that if x and y are jets, then the derivative information is -// correctly propagated. +// Sample the image at position (x, y) but use the gradient, if present, to +// propagate derivatives from x and y. This is needed to integrate the numeric +// image gradients with Ceres's autodiff framework. template static T SampleWithDerivative(const FloatImage &image_and_gradient, const T &x, @@ -172,7 +172,7 @@ class WarpCostFunctor { // Sample the pattern and gradients. SampleLinear(image_and_gradient1_, - image_position(1), // Sample is r, c. + image_position(1), // SampleLinear is r, c. image_position(0), &pattern_and_gradient_(r, c, 0)); @@ -180,7 +180,7 @@ class WarpCostFunctor { double mask_value = 1.0; if (options_.image1_mask != NULL) { SampleLinear(*options_.image1_mask, - image_position(1), + image_position(1), // SampleLinear is r, c. image_position(0), &pattern_mask_(r, c, 0)); mask_value = pattern_mask_(r, c); @@ -216,6 +216,16 @@ class WarpCostFunctor { // Sample the mask early; if it's zero, this pixel has no effect. This // allows early bailout from the expensive sampling that happens below. + // + // Note that partial masks are not short circuited. To see why short + // circuiting produces bitwise-exact same results, consider that the + // residual for each pixel is + // + // residual = mask * (src - dst) , + // + // and for jets, multiplying by a scalar multiplies the derivative + // components by the scalar as well. Therefore, if the mask is exactly + // zero, then so too will the final residual and derivatives. double mask_value = 1.0; if (options_.image1_mask != NULL) { mask_value = pattern_mask_(r, c); @@ -240,7 +250,7 @@ class WarpCostFunctor { // Sample the source. This is made complicated by ESM mode. T src_sample; - if (0 && options_.use_esm && !JetOps::IsScalar()) { + if (options_.use_esm && !JetOps::IsScalar()) { // In ESM mode, the derivative of the source is also taken into // account. This changes the linearization in a way that causes // better convergence. Copy the derivative of the warp parameters @@ -270,8 +280,6 @@ class WarpCostFunctor { src_sample = T(pattern_and_gradient_(r, c)); } - //LG << "src_sample: " << src_sample; - // Normalize the samples by the mean values of each signal. The typical // light model assumes multiplicative intensity changes with changing // light, so this is a reasonable choice. Note that dst_mean has @@ -281,8 +289,6 @@ class WarpCostFunctor { dst_sample /= dst_mean; } - //LG << "dst_sample: " << dst_sample; - // The difference is the error. T error = src_sample - dst_sample; @@ -389,8 +395,8 @@ class WarpCostFunctor { double x = pattern_and_gradient_(r, c); double y = SampleLinear(image_and_gradient2_, - image2_position[0], - image2_position[1]); + image2_position[1], // SampleLinear is r, c. + image2_position[0]); // Weight the signals by the mask, if one is present. if (options_.image1_mask != NULL) { @@ -1111,13 +1117,14 @@ void TemplatedTrackRegion(const FloatImage &image1, x1, y1, x2, y2); for (int i = 0; i < 4; ++i) { LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); brute (" - << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", " - << (y2[i] - y1[i]) << ")."; + << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) + << ", " << (y2[i] - y1[i]) << ")."; } } // Prepare the initial warp parameters from the four correspondences. - // Note: This must happen after the brute initialization runs. + // Note: This must happen after the brute initialization runs, since the + // brute initialization mutates x2 and y2 in place. Warp warp(x1, y1, x2, y2); // Decide how many samples to use in the x and y dimensions. @@ -1125,22 +1132,6 @@ void TemplatedTrackRegion(const FloatImage &image1, int num_samples_y; PickSampling(x1, y1, x2, y2, &num_samples_x, &num_samples_y); - ceres::Solver::Options solver_options; - solver_options.linear_solver_type = ceres::DENSE_QR; - solver_options.max_num_iterations = options.max_iterations; - solver_options.update_state_every_iteration = true; - solver_options.parameter_tolerance = 1e-16; - solver_options.function_tolerance = 1e-16; - - // TODO(keir): Consider removing these options before committing. - solver_options.numeric_derivative_relative_step_size = 1e-3; - solver_options.check_gradients = false; - solver_options.gradient_check_relative_precision = 1e-10; - solver_options.minimizer_progress_to_stdout = false; - - // Prevent the corners from going outside the destination image. - BoundaryCheckingCallback callback(image2, warp, x1, y1); - solver_options.callbacks.push_back(&callback); // Compute the warp from rectangular coordinates. Mat3 canonical_homography = ComputeCanonicalHomography(x1, y1, @@ -1158,9 +1149,7 @@ void TemplatedTrackRegion(const FloatImage &image1, warp); // Construct the problem with a single residual. - ceres::Problem::Options problem_options; - problem_options.cost_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; - ceres::Problem problem(problem_options); + ceres::Problem problem; problem.AddResidualBlock( new ceres::AutoDiffCostFunction< WarpCostFunctor, @@ -1170,6 +1159,19 @@ void TemplatedTrackRegion(const FloatImage &image1, NULL, warp.parameters); + // Configure the solve. + ceres::Solver::Options solver_options; + solver_options.linear_solver_type = ceres::DENSE_QR; + solver_options.max_num_iterations = options.max_iterations; + solver_options.update_state_every_iteration = true; + solver_options.parameter_tolerance = 1e-16; + solver_options.function_tolerance = 1e-16; + + // Prevent the corners from going outside the destination image. + BoundaryCheckingCallback callback(image2, warp, x1, y1); + solver_options.callbacks.push_back(&callback); + + // Run the solve. ceres::Solver::Summary summary; ceres::Solve(solver_options, &problem, &summary); diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h index ca21090e7c0..c23cde6000f 100644 --- a/extern/libmv/libmv/tracking/track_region.h +++ b/extern/libmv/libmv/tracking/track_region.h @@ -114,10 +114,10 @@ void TrackRegion(const FloatImage &image1, TrackRegionResult *result); // Sample a "canonical" version of the passed planar patch, using bilinear -// sampling. The passed corners must be within the image, possibly with a small -// amount of slop, perhaps 2 pixels, around the edges (so e.g. a corner of the -// patch cannot lie directly on the edge of the image). Four corners are always -// required. All channels are interpolated. +// sampling. The passed corners must be within the image, and have at least two +// pixels of border around them. (so e.g. a corner of the patch cannot lie +// directly on the edge of the image). Four corners are always required. All +// channels are interpolated. bool SamplePlanarPatch(const FloatImage &image, const double *xs, const double *ys, int num_samples_x, int num_samples_y, From 039acbbfef112e140a47dcab05a40d732d293deb Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 Jun 2012 11:14:36 +0000 Subject: [PATCH 170/183] Homography correction for track preview widget Use homography transformation for pattern displayed in track preview widget. Sampling of this pattern happens to resolution of preview widget itself, which implied some bigger changes in how scopes are working: - Instead of real pattern store search area in BKE_movieclip_update_scopes, which is later used for sampling pattern. - Sampling of pattern happens in ui_draw_but_TRACKPREVIEW from search area which allows to sample it to actual resolution of preview widget. - If size of preview widget is not changing, this sampled pattern wouldn't be re-sampled until scopes are tagged to update. There are some issues with pattern sampling which seems to happen SamplePlanarPatch, changing linear sampling to nearest removes that unwanted 1px offset. Left commented saving of sampled image in ui_draw_but_TRACKPREVIEW which should help figuring the issue out. --- extern/libmv/libmv-capi.cpp | 46 ++- extern/libmv/libmv-capi.h | 5 + extern/libmv/libmv/tracking/track_region.cc | 10 +- extern/libmv/libmv/tracking/track_region.h | 3 +- source/blender/blenkernel/BKE_tracking.h | 10 +- source/blender/blenkernel/intern/movieclip.c | 26 +- source/blender/blenkernel/intern/tracking.c | 298 +++++++++--------- source/blender/blenloader/intern/readfile.c | 1 + .../operations/COM_KeyingScreenOperation.cpp | 2 +- .../editors/interface/interface_draw.c | 84 +++-- .../blender/editors/space_clip/space_clip.c | 4 + source/blender/makesdna/DNA_movieclip_types.h | 3 + .../nodes/node_composite_keyingscreen.c | 2 +- 13 files changed, 264 insertions(+), 230 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index eba4698f198..ffa065f08fe 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -163,15 +163,30 @@ libmv_RegionTracker *libmv_bruteRegionTrackerNew(int half_window_size, double mi return (libmv_RegionTracker *)brute_region_tracker; } -static void floatBufToImage(const float *buf, int width, int height, libmv::FloatImage *image) +static void floatBufToImage(const float *buf, int width, int height, int channels, libmv::FloatImage *image) { - int x, y, a = 0; + int x, y, k, a = 0; - image->resize(height, width); + image->Resize(height, width, channels); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - (*image)(y, x, 0) = buf[a++]; + for (k = 0; k < channels; k++) { + (*image)(y, x, k) = buf[a++]; + } + } + } +} + +static void imageToFloatBuf(const libmv::FloatImage *image, int channels, float *buf) +{ + int x, y, k, a = 0; + + for (y = 0; y < image->Height(); y++) { + for (x = 0; x < image->Width(); x++) { + for (k = 0; k < channels; k++) { + buf[a++] = (*image)(y, x, k); + } } } } @@ -307,8 +322,8 @@ int libmv_regionTrackerTrack(libmv_RegionTracker *libmv_tracker, const float *im libmv::RegionTracker *region_tracker = (libmv::RegionTracker *)libmv_tracker; libmv::FloatImage old_patch, new_patch; - floatBufToImage(ima1, width, height, &old_patch); - floatBufToImage(ima2, width, height, &new_patch); + floatBufToImage(ima1, width, height, 1, &old_patch); + floatBufToImage(ima2, width, height, 1, &new_patch); #if !defined(DUMP_FAILURE) && !defined(DUMP_ALWAYS) return region_tracker->Track(old_patch, new_patch, x1, y1, x2, y2); @@ -385,8 +400,8 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options, /* Convert from raw float buffers to libmv's FloatImage. */ libmv::FloatImage old_patch, new_patch; - floatBufToImage(image1, width, height, &old_patch); - floatBufToImage(image2, width, height, &new_patch); + floatBufToImage(image1, width, height, 1, &old_patch); + floatBufToImage(image2, width, height, 1, &new_patch); libmv::TrackRegionResult track_region_result; libmv::TrackRegion(old_patch, new_patch, xx1, yy1, track_region_options, xx2, yy2, &track_region_result); @@ -420,6 +435,21 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options, return tracking_result; } +void libmv_samplePlanarPatch(const float *image, int width, int height, + int channels, const double *xs, const double *ys, + int num_samples_x, int num_samples_y, float *patch, + double *warped_position_x, double *warped_position_y) +{ + libmv::FloatImage libmv_image, libmv_patch; + + floatBufToImage(image, width, height, channels, &libmv_image); + + libmv::SamplePlanarPatch(libmv_image, xs, ys, num_samples_x, num_samples_y, + &libmv_patch, warped_position_x, warped_position_y); + + imageToFloatBuf(&libmv_patch, channels, patch); +} + /* ************ Tracks ************ */ libmv_Tracks *libmv_tracksNew(void) diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index bbd8f0c30d0..6f4b5dea384 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -71,6 +71,11 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options, struct libmv_trackRegionResult *result, double *x2, double *y2); +void libmv_samplePlanarPatch(const float *image, int width, int height, + int channels, const double *xs, const double *ys, + int num_samples_x, int num_samples_y, float *patch, + double *warped_position_x, double *warped_position_y); + /* Tracks */ struct libmv_Tracks *libmv_tracksNew(void); void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track, double x, double y); diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index b9e4f883e78..679646c4c37 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -1252,7 +1252,8 @@ void TrackRegion(const FloatImage &image1, bool SamplePlanarPatch(const FloatImage &image, const double *xs, const double *ys, int num_samples_x, int num_samples_y, - FloatImage *patch) { + FloatImage *patch, + double *warped_position_x, double *warped_position_y) { // Bail early if the points are outside the image. if (!AllInBounds(image, xs, ys)) { LG << "Can't sample patch: out of bounds."; @@ -1278,6 +1279,13 @@ bool SamplePlanarPatch(const FloatImage &image, &(*patch)(r, c, 0)); } } + + Vec3 warped_position = canonical_homography.inverse() * Vec3(xs[4], ys[4], 1); + warped_position /= warped_position(2); + + *warped_position_x = warped_position(0); + *warped_position_y = warped_position(1); + return true; } diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h index c23cde6000f..04e7c7e1403 100644 --- a/extern/libmv/libmv/tracking/track_region.h +++ b/extern/libmv/libmv/tracking/track_region.h @@ -121,7 +121,8 @@ void TrackRegion(const FloatImage &image1, bool SamplePlanarPatch(const FloatImage &image, const double *xs, const double *ys, int num_samples_x, int num_samples_y, - FloatImage *patch); + FloatImage *patch, + double *warped_position_x, double *warped_position_y); } // namespace libmv diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 25723b8b0e8..8c28dd93a5e 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -71,13 +71,13 @@ void BKE_tracking_clear_path(struct MovieTrackingTrack *track, int ref_frame, in void BKE_tracking_join_tracks(struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track); void BKE_tracking_free(struct MovieTracking *tracking); +struct ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, + struct ImBuf *struct_ibuf, struct MovieTrackingMarker *marker, + int num_samples_x, int num_samples_y, float pos[2]); struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int margin, int anchored, - float pos[2], int origin[2]); -struct ImBuf *BKE_tracking_get_pattern_color_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int anchored); + struct MovieTrackingMarker *marker, int anchored, int disable_channels); struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker); + struct MovieTrackingMarker *marker, int anchored, int disable_channels); struct ImBuf *BKE_tracking_track_mask_get(struct MovieTracking *tracking, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int width, int height); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 244d2888fc6..8b91ee29c59 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1032,6 +1032,11 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip scopes->track_preview = NULL; } + if (scopes->track_search) { + IMB_freeImBuf(scopes->track_search); + scopes->track_search = NULL; + } + scopes->marker = NULL; scopes->track = NULL; @@ -1052,7 +1057,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip scopes->track_disabled = FALSE; if (ibuf && (ibuf->rect || ibuf->rect_float)) { - ImBuf *tmpibuf; + ImBuf *search_ibuf; MovieTrackingMarker undist_marker = *marker; if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) { @@ -1070,17 +1075,18 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip undist_marker.pos[1] /= height * aspy; } - /* NOTE: margin should be kept in sync with value from ui_draw_but_TRACKPREVIEW */ - tmpibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 3 /* margin */, - 1 /* anchor */, scopes->track_pos, NULL); + search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, TRUE, TRUE); - if (tmpibuf->rect_float) - IMB_rect_from_float(tmpibuf); + if (!search_ibuf->rect_float) { + /* sampling happens in float buffer */ + IMB_float_from_rect(search_ibuf); + } - if (tmpibuf->rect) - scopes->track_preview = tmpibuf; - else - IMB_freeImBuf(tmpibuf); + scopes->undist_marker = undist_marker; + scopes->track_search = search_ibuf; + + scopes->frame_width = ibuf->x; + scopes->frame_height = ibuf->y; } IMB_freeImBuf(ibuf); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 01e464e77a8..1d4ed2c8c40 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -84,10 +84,11 @@ static struct { * window relative coordinates in pixels, and "frame_unified" are unified 0..1 * coordinates relative to the entire frame. */ -static void unified_to_pixel(const ImBuf *ibuf, const float unified_coords[2], float pixel_coords[2]) +static void unified_to_pixel(int frame_width, int frame_height, + const float unified_coords[2], float pixel_coords[2]) { - pixel_coords[0] = unified_coords[0] * ibuf->x; - pixel_coords[1] = unified_coords[1] * ibuf->y; + pixel_coords[0] = unified_coords[0] * frame_width; + pixel_coords[1] = unified_coords[1] * frame_height; } static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2], @@ -97,52 +98,117 @@ static void marker_to_frame_unified(const MovieTrackingMarker *marker, const flo frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1]; } -static void marker_unified_to_frame_pixel_coordinates(const ImBuf *ibuf, const MovieTrackingMarker *marker, +static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height, + const MovieTrackingMarker *marker, const float marker_unified_coords[2], float frame_pixel_coords[2]) { marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords); - unified_to_pixel(ibuf, frame_pixel_coords, frame_pixel_coords); + unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords); } -static void get_search_origin_frame_pixel(const ImBuf *ibuf, const MovieTrackingMarker *marker, float frame_pixel[2]) +static void get_search_origin_frame_pixel(int frame_width, int frame_height, + const MovieTrackingMarker *marker, float frame_pixel[2]) { /* Get the lower left coordinate of the search window and snap to pixel coordinates */ - marker_unified_to_frame_pixel_coordinates(ibuf, marker, marker->search_min, frame_pixel); + marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker->search_min, frame_pixel); frame_pixel[0] = (int)frame_pixel[0]; frame_pixel[1] = (int)frame_pixel[1]; } #ifdef WITH_LIBMV -static void pixel_to_unified(const ImBuf *ibuf, const float pixel_coords[2], float unified_coords[2]) +static void pixel_to_unified(int frame_width, int frame_height, const float pixel_coords[2], float unified_coords[2]) { - unified_coords[0] = pixel_coords[0] / ibuf->x; - unified_coords[1] = pixel_coords[1] / ibuf->y; + unified_coords[0] = pixel_coords[0] / frame_width; + unified_coords[1] = pixel_coords[1] / frame_height; } -static void marker_unified_to_search_pixel(const ImBuf *ibuf, const MovieTrackingMarker *marker, +static void marker_unified_to_search_pixel(int frame_width, int frame_height, + const MovieTrackingMarker *marker, const float marker_unified[2], float search_pixel[2]) { float frame_pixel[2]; float search_origin_frame_pixel[2]; - marker_unified_to_frame_pixel_coordinates(ibuf, marker, marker_unified, frame_pixel); - get_search_origin_frame_pixel(ibuf, marker, search_origin_frame_pixel); + marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker_unified, frame_pixel); + get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel); sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel); } -static void search_pixel_to_marker_unified(const ImBuf *ibuf, const MovieTrackingMarker *marker, +static void search_pixel_to_marker_unified(int frame_width, int frame_height, + const MovieTrackingMarker *marker, const float search_pixel[2], float marker_unified[2]) { float frame_unified[2]; float search_origin_frame_pixel[2]; - get_search_origin_frame_pixel(ibuf, marker, search_origin_frame_pixel); + get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel); add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel); - pixel_to_unified(ibuf, frame_unified, frame_unified); + pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified); /* marker pos is in frame unified */ sub_v2_v2v2(marker_unified, frame_unified, marker->pos); } + +/* Each marker has 5 coordinates associated with it that get warped with + * tracking: the four corners ("pattern_corners"), and the cernter ("pos"). + * This function puts those 5 points into the appropriate frame for tracking + * (the "search" coordinate frame). + */ +static void get_marker_coords_for_tracking(int frame_width, int frame_height, + const MovieTrackingMarker *marker, + double search_pixel_x[5], double search_pixel_y[5]) +{ + int i; + float unified_coords[2]; + float pixel_coords[2]; + + /* Convert the corners into search space coordinates. */ + for (i = 0; i < 4; i++) { + marker_unified_to_search_pixel(frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords); + search_pixel_x[i] = pixel_coords[0]; + search_pixel_y[i] = pixel_coords[1]; + } + /* Convert the center position (aka "pos"); this is the origin */ + unified_coords[0] = 0.0; + unified_coords[1] = 0.0; + marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords); + + search_pixel_x[4] = pixel_coords[0]; + search_pixel_y[4] = pixel_coords[1]; +} + +/* Inverse of above. */ +static void set_marker_coords_from_tracking(int frame_width, int frame_height, MovieTrackingMarker *marker, + const double search_pixel_x[5], const double search_pixel_y[5]) +{ + int i; + float marker_unified[2]; + float search_pixel[2]; + + /* Convert the corners into search space coordinates. */ + for (i = 0; i < 4; i++) { + search_pixel[0] = search_pixel_x[i]; + search_pixel[1] = search_pixel_y[i]; + search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]); + } + + /* Convert the center position (aka "pos"); this is the origin */ + search_pixel[0] = search_pixel_x[4]; + search_pixel[1] = search_pixel_y[4]; + search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified); + + /* If the tracker tracked nothing, then "marker_unified" would be zero. + * Otherwise, the entire patch shifted, and that delta should be applied to + * all the coordinates. + */ + for (i = 0; i < 4; i++) { + marker->pattern_corners[i][0] -= marker_unified[0]; + marker->pattern_corners[i][1] -= marker_unified[1]; + } + + marker->pos[0] += marker_unified[0]; + marker->pos[1] += marker_unified[1]; +} #endif /*********************** common functions *************************/ @@ -1178,102 +1244,75 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g track->flag & TRACK_DISABLE_GREEN, track->flag & TRACK_DISABLE_BLUE, grayscale); } -static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - float min[2], float max[2], int margin, int anchored, - int grayscale, float pos[2], int origin[2]) +ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, + ImBuf *search_ibuf, MovieTrackingMarker *marker, + int num_samples_x, int num_samples_y, float pos[2]) { - ImBuf *tmpibuf; - int x, y; - int x1, y1, w, h; - float mpos[2]; + ImBuf *pattern_ibuf; + double src_pixel_x[5], src_pixel_y[5]; + double warped_position_x, warped_position_y; - copy_v2_v2(mpos, marker->pos); - if (anchored) - add_v2_v2(mpos, track->offset); + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); + pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB; - if (pos) - zero_v2(pos); - - x = mpos[0]*ibuf->x; - y = mpos[1]*ibuf->y; - - w = (max[0] - min[0]) * ibuf->x; - h = (max[1] - min[1]) * ibuf->y; - - /* dimensions should be odd */ - w = w | 1; - h = h | 1; - - x1 = x - (int)(w * (-min[0] / (max[0] - min[0]))); - y1 = y - (int)(h * (-min[1] / (max[1] - min[1]))); - - if (ibuf->rect_float) - tmpibuf = IMB_allocImBuf(w + margin * 2, h + margin * 2, 32, IB_rectfloat); - else - tmpibuf = IMB_allocImBuf(w + margin * 2, h + margin * 2, 32, IB_rect); - - tmpibuf->profile = ibuf->profile; - - IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1 - margin, y1 - margin, w + margin * 2, h + margin * 2); - - if (pos != NULL) { - pos[0] = mpos[0] * ibuf->x - x1 + margin; - pos[1] = mpos[1] * ibuf->y - y1 + margin; + if (!search_ibuf->rect_float) { + IMB_float_from_rect(search_ibuf); } - if (origin != NULL) { - origin[0] = x1 - margin; - origin[1] = y1 - margin; + get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y); + + libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4, + src_pixel_x, src_pixel_y, num_samples_x, + num_samples_y, pattern_ibuf->rect_float, + &warped_position_x, &warped_position_y); + + if (pos) { + pos[0] = warped_position_x; + pos[1] = warped_position_y; } - if (grayscale) { - if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || - (track->flag & TRACK_DISABLE_RED) || - (track->flag & TRACK_DISABLE_GREEN) || - (track->flag & TRACK_DISABLE_BLUE)) - { - disable_imbuf_channels(tmpibuf, track, TRUE /* grayscale */); - } - } - - return tmpibuf; + return pattern_ibuf; } ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int margin, int anchored, float pos[2], int origin[2]) + int anchored, int disable_channels) { + ImBuf *pattern_ibuf, *search_ibuf; float pat_min[2], pat_max[2]; + int num_samples_x, num_samples_y; - /* XXX: need to do real quad sampling here, but currently just assume - * corners represents quad pattern - */ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, margin, anchored, TRUE, pos, origin); + num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x; + num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y; + + search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels); + + pattern_ibuf = BKE_tracking_sample_pattern_imbuf(ibuf->x, ibuf->y, search_ibuf, marker, + num_samples_x, num_samples_y, NULL); + + IMB_freeImBuf(search_ibuf); + + return pattern_ibuf; } -ImBuf *BKE_tracking_get_pattern_color_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, - MovieTrackingMarker *marker, int anchored) -{ - float pat_min[2], pat_max[2]; - - /* see comment above */ - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - - return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, 0, anchored, FALSE, NULL, NULL); -} - -ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker) +ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int anchored, int disable_channels) { ImBuf *searchibuf; int x, y, w, h; float search_origin[2]; - get_search_origin_frame_pixel(ibuf, marker, search_origin); + get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin); x = search_origin[0]; y = search_origin[1]; + if (anchored) { + x += track->offset[0] * ibuf->x; + y += track->offset[1] * ibuf->y; + } + w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x; h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; @@ -1282,12 +1321,14 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); - if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || - (track->flag & TRACK_DISABLE_RED) || - (track->flag & TRACK_DISABLE_GREEN) || - (track->flag & TRACK_DISABLE_BLUE)) - { - disable_imbuf_channels(searchibuf, track, FALSE); + if (disable_channels) { + if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || + (track->flag & TRACK_DISABLE_RED) || + (track->flag & TRACK_DISABLE_GREEN) || + (track->flag & TRACK_DISABLE_BLUE)) + { + disable_imbuf_channels(searchibuf, track, TRUE); + } } return searchibuf; @@ -1424,7 +1465,7 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT float *gray_pixels; int width, height; - searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker); + searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, FALSE, TRUE); width = searchibuf->x; height = searchibuf->y; @@ -1448,66 +1489,6 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT return gray_pixels; } -/* Each marker has 5 coordinates associated with it that get warped with - * tracking: the four corners ("pattern_corners"), and the cernter ("pos"). - * This function puts those 5 points into the appropriate frame for tracking - * (the "search" coordinate frame). - */ -static void get_marker_coords_for_tracking(const ImBuf *ibuf, const MovieTrackingMarker *marker, - double search_pixel_x[5], double search_pixel_y[5]) -{ - int i; - float unified_coords[2]; - float pixel_coords[2]; - - /* Convert the corners into search space coordinates. */ - for (i = 0; i < 4; i++) { - marker_unified_to_search_pixel(ibuf, marker, marker->pattern_corners[i], pixel_coords); - search_pixel_x[i] = pixel_coords[0]; - search_pixel_y[i] = pixel_coords[1]; - } - /* Convert the center position (aka "pos"); this is the origin */ - unified_coords[0] = 0.0; - unified_coords[1] = 0.0; - marker_unified_to_search_pixel(ibuf, marker, unified_coords, pixel_coords); - - search_pixel_x[4] = pixel_coords[0]; - search_pixel_y[4] = pixel_coords[1]; -} - -/* Inverse of above. */ -static void set_marker_coords_from_tracking(const ImBuf *ibuf, MovieTrackingMarker *marker, - const double search_pixel_x[5], const double search_pixel_y[5]) -{ - int i; - float marker_unified[2]; - float search_pixel[2]; - - /* Convert the corners into search space coordinates. */ - for (i = 0; i < 4; i++) { - search_pixel[0] = search_pixel_x[i]; - search_pixel[1] = search_pixel_y[i]; - search_pixel_to_marker_unified(ibuf, marker, search_pixel, marker->pattern_corners[i]); - } - - /* Convert the center position (aka "pos"); this is the origin */ - search_pixel[0] = search_pixel_x[4]; - search_pixel[1] = search_pixel_y[4]; - search_pixel_to_marker_unified(ibuf, marker, search_pixel, marker_unified); - - /* If the tracker tracked nothing, then "marker_unified" would be zero. - * Otherwise, the entire patch shifted, and that delta should be applied to - * all the coordinates. - */ - for (i = 0; i < 4; i++) { - marker->pattern_corners[i][0] -= marker_unified[0]; - marker->pattern_corners[i][1] -= marker_unified[1]; - } - - marker->pos[0] += marker_unified[0]; - marker->pos[1] += marker_unified[1]; -} - static unsigned char *get_ucharbuf(ImBuf *ibuf) { int x, y; @@ -1633,6 +1614,8 @@ int BKE_tracking_next(MovieTrackingContext *context) int curfra = BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr); int a, ok = FALSE, map_size; + int frame_width, frame_height; + map_size = tracks_map_size(context->tracks_map); /* nothing to track, avoid unneeded frames reading to save time and memory */ @@ -1649,6 +1632,9 @@ int BKE_tracking_next(MovieTrackingContext *context) if (!destination_ibuf) return FALSE; + frame_width = destination_ibuf->x; + frame_height = destination_ibuf->y; + #pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size>1) for (a = 0; a < map_size; a++) { TrackContext *track_context = NULL; @@ -1739,8 +1725,8 @@ int BKE_tracking_next(MovieTrackingContext *context) options.sigma = 0.9; /* Convert the marker corners and center into pixel coordinates in the search/destination images. */ - get_marker_coords_for_tracking(destination_ibuf, &track_context->marker, src_pixel_x, src_pixel_y); - get_marker_coords_for_tracking(destination_ibuf, marker, dst_pixel_x, dst_pixel_y); + get_marker_coords_for_tracking(frame_width, frame_height, &track_context->marker, src_pixel_x, src_pixel_y); + get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y); /* Run the tracker! */ tracked = libmv_trackRegion(&options, @@ -1755,7 +1741,7 @@ int BKE_tracking_next(MovieTrackingContext *context) if (tracked && !onbound) { memset(&marker_new, 0, sizeof(marker_new)); marker_new = *marker; - set_marker_coords_from_tracking(destination_ibuf, &marker_new, dst_pixel_x, dst_pixel_y); + set_marker_coords_from_tracking(frame_width, frame_height, &marker_new, dst_pixel_x, dst_pixel_y); marker_new.flag |= MARKER_TRACKED; marker_new.framenr = nextfra; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a36645510c3..a1d255e67e8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5362,6 +5362,7 @@ static void lib_link_screen(FileData *fd, Main *main) sclip->clip = newlibadr_us(fd, sc->id.lib, sclip->clip); sclip->mask = newlibadr_us(fd, sc->id.lib, sclip->mask); + sclip->scopes.track_search = NULL; sclip->scopes.track_preview = NULL; sclip->draw_context = NULL; sclip->scopes.ok = 0; diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index 4f6abdcbc22..1bb0d90c1db 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -116,7 +116,7 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri while (track) { VoronoiSite *site = &sites[i]; MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenumber); - ImBuf *pattern_ibuf = BKE_tracking_get_pattern_color_imbuf(ibuf, track, marker, TRUE); + ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE); int j; zero_v3(site->color); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index a0b418c1a9a..d652fe4a569 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -43,6 +43,7 @@ #include "BKE_colortools.h" #include "BKE_texture.h" +#include "BKE_tracking.h" #include "IMB_imbuf.h" @@ -1480,36 +1481,10 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *rect fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax); } -static ImBuf *scale_trackpreview_ibuf(ImBuf *ibuf, float track_pos[2], int width, float height, int margin) -{ - ImBuf *scaleibuf; - const float scalex = ((float)ibuf->x - 2 * margin) / width; - const float scaley = ((float)ibuf->y - 2 * margin) / height; - /* NOTE: 1.0f = 0.5f for integer coordinate coorrection (center of pixel vs. left bottom corner of bixel) - * and 0.5f for centering image in preview (cross is draving at exact center of widget so image - * should be shifted by half of pixel for correct centering) - sergey */ - float off_x = (int)track_pos[0] - track_pos[0] + 1.0f; - float off_y = (int)track_pos[1] - track_pos[1] + 1.0f; - int x, y; - - scaleibuf = IMB_allocImBuf(width, height, 32, IB_rect); - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - float src_x = scalex * (x) + margin - off_x; - float src_y = scaley * (y) + margin - off_y; - - bicubic_interpolation(ibuf, scaleibuf, src_x, src_y, x, y); - } - } - - return scaleibuf; -} - void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti) { rctf rect; - int ok = 0; + int ok = 0, width, height; GLint scissor[4]; MovieClipScopes *scopes = (MovieClipScopes *)but->poin; @@ -1518,6 +1493,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; rect.ymax = (float)recti->ymax - 1; + width = rect.xmax - rect.xmin + 1; + height = rect.ymax - rect.ymin; + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1535,40 +1513,52 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc ok = 1; } - else if (scopes->track_preview) { - /* additional margin around image */ - /* NOTE: should be kept in sync with value from BKE_movieclip_update_scopes */ - const int margin = 3; - float zoomx, zoomy, track_pos[2], off_x, off_y; - int a, width, height; + else if ((!scopes->track_preview) || + (scopes->track_preview->x != width || scopes->track_preview->y != height)) + { + ImBuf *tmpibuf; + + if (scopes->track_preview) + IMB_freeImBuf(scopes->track_preview); + + tmpibuf = BKE_tracking_sample_pattern_imbuf(scopes->frame_width, scopes->frame_height, + scopes->track_search, &scopes->undist_marker, + width, height, scopes->track_pos); + + if (tmpibuf->rect_float) + IMB_rect_from_float(tmpibuf); + + // XXX: for debug only + // tmpibuf->ftype = PNG; + // IMB_saveiff(tmpibuf, "sample.png", IB_rect); + + if (tmpibuf->rect) + scopes->track_preview = tmpibuf; + else + IMB_freeImBuf(tmpibuf); + } + + if (!ok && scopes->track_preview) { + float track_pos[2]; + int a; ImBuf *drawibuf; glPushMatrix(); - track_pos[0] = scopes->track_pos[0] - margin; - track_pos[1] = scopes->track_pos[1] - margin; + track_pos[0] = scopes->track_pos[0]; + track_pos[1] = scopes->track_pos[1]; /* draw content of pattern area */ glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]); - width = rect.xmax - rect.xmin + 1; - height = rect.ymax - rect.ymin; - if (width > 0 && height > 0) { - zoomx = (float)width / (scopes->track_preview->x - 2 * margin); - zoomy = (float)height / (scopes->track_preview->y - 2 * margin); - - off_x = ((int)track_pos[0] - track_pos[0] + 0.5f) * zoomx; - off_y = ((int)track_pos[1] - track_pos[1] + 0.5f) * zoomy; - - drawibuf = scale_trackpreview_ibuf(scopes->track_preview, track_pos, width, height, margin); + drawibuf = scopes->track_preview; glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, drawibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, drawibuf->rect); - IMB_freeImBuf(drawibuf); /* draw cross for pizel position */ - glTranslatef(off_x + rect.xmin + track_pos[0] * zoomx, off_y + rect.ymin + track_pos[1] * zoomy, 0.f); + glTranslatef(rect.xmin + track_pos[0], rect.ymin + track_pos[1], 0.f); glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, rect.xmax - rect.xmin, diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index a49319abd20..54724881e37 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -306,6 +306,9 @@ static void clip_free(SpaceLink *sl) if (sc->scopes.track_preview) IMB_freeImBuf(sc->scopes.track_preview); + if (sc->scopes.track_search) + IMB_freeImBuf(sc->scopes.track_search); + ED_space_clip_free_texture_buffer(sc); } @@ -323,6 +326,7 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) SpaceClip *scn = MEM_dupallocN(sl); /* clear or remove stuff from old */ + scn->scopes.track_search = NULL; scn->scopes.track_preview = NULL; scn->scopes.ok = FALSE; scn->draw_context = NULL; diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index fd7046854ff..b9d63167700 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -92,6 +92,9 @@ typedef struct MovieClip { typedef struct MovieClipScopes { int ok; /* 1 means scopes are ok and recalculation is unneeded */ int track_preview_height; /* height of track preview widget */ + int frame_width, frame_height; /* width and height of frame for which scopes are calculated */ + struct MovieTrackingMarker undist_marker; /* undistorted position of marker used for pattern sampling */ + struct ImBuf *track_search; /* search area of a track */ struct ImBuf *track_preview; /* ImBuf displayed in track preview */ float track_pos[2]; /* sub-pizel position of marker in track ImBuf */ short track_disabled; /* active track is disabled, special notifier should be drawn */ diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c index b7ce621a9e1..6149285fdbc 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c +++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c @@ -91,7 +91,7 @@ static void compute_gradient_screen(RenderData *rd, NodeKeyingScreenData *keying while (track) { VoronoiSite *site = &sites[i]; MovieTrackingMarker *marker = BKE_tracking_get_marker(track, rd->cfra); - ImBuf *pattern_ibuf = BKE_tracking_get_pattern_color_imbuf(ibuf, track, marker, TRUE); + ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE); int j; zero_v3(site->color); From 5fe661792c230ac97d85477354a01e3d7aa1149a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 Jun 2012 11:34:22 +0000 Subject: [PATCH 171/183] Fixed crash in previous commit when track preview is drawing for missed frame --- source/blender/blenkernel/intern/tracking.c | 2 +- source/blender/editors/interface/interface_draw.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 1d4ed2c8c40..938bff81470 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1246,7 +1246,7 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, ImBuf *search_ibuf, MovieTrackingMarker *marker, - int num_samples_x, int num_samples_y, float pos[2]) + int num_samples_x, int num_samples_y, float pos[2]) { ImBuf *pattern_ibuf; double src_pixel_x[5], src_pixel_y[5]; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index d652fe4a569..6f6de0cc418 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -1513,8 +1513,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc ok = 1; } - else if ((!scopes->track_preview) || - (scopes->track_preview->x != width || scopes->track_preview->y != height)) + else if ((scopes->track_search) && + ((!scopes->track_preview) || + (scopes->track_preview->x != width || scopes->track_preview->y != height))) { ImBuf *tmpibuf; From 6b13203a9ca59c0b066327781e7fc3f4bd7dd9cf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 Jun 2012 17:15:38 +0000 Subject: [PATCH 172/183] Changes to keying nodes: - Replace FastGaussian blur with GaussianBokeh blur which should give better results. - Changes a bit formula of saturation which in some cases gives better result. Also included (commented out) original formula which was also checked by Brecht and which gave better result in some other cases. - Made clipping white/black temporal dependent, so hopefully it wouldn't destroy gradients on edges. --- source/blender/compositor/CMakeLists.txt | 2 + .../compositor/nodes/COM_KeyingNode.cpp | 35 +++++-- .../blender/compositor/nodes/COM_KeyingNode.h | 1 + .../operations/COM_KeyingClipOperation.cpp | 95 +++++++++++++++++++ .../operations/COM_KeyingClipOperation.h | 50 ++++++++++ .../operations/COM_KeyingOperation.cpp | 56 +++++------ .../operations/COM_KeyingOperation.h | 5 - source/blender/makesrna/intern/rna_nodetree.c | 2 +- 8 files changed, 200 insertions(+), 46 deletions(-) create mode 100644 source/blender/compositor/operations/COM_KeyingClipOperation.cpp create mode 100644 source/blender/compositor/operations/COM_KeyingClipOperation.h diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index c71168b2d2e..6fc938c192c 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -333,6 +333,8 @@ set(SRC operations/COM_KeyingScreenOperation.h operations/COM_KeyingDespillOperation.cpp operations/COM_KeyingDespillOperation.h + operations/COM_KeyingClipOperation.cpp + operations/COM_KeyingClipOperation.h operations/COM_ColorSpillOperation.cpp operations/COM_ColorSpillOperation.h diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp index 9e29a99293e..2bc502a5f86 100644 --- a/source/blender/compositor/nodes/COM_KeyingNode.cpp +++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp @@ -27,12 +27,13 @@ #include "COM_KeyingOperation.h" #include "COM_KeyingDespillOperation.h" +#include "COM_KeyingClipOperation.h" #include "COM_SeparateChannelOperation.h" #include "COM_CombineChannelsOperation.h" #include "COM_ConvertRGBToYCCOperation.h" #include "COM_ConvertYCCToRGBOperation.h" -#include "COM_FastGaussianBlurOperation.h" +#include "COM_GaussianBokehBlurOperation.h" #include "COM_SetValueOperation.h" #include "COM_DilateErodeOperation.h" @@ -72,8 +73,9 @@ OutputSocket *KeyingNode::setupPreBlur(ExecutionSystem *graph, InputSocket *inpu setValueOperation->setValue(1.0f); graph->addOperation(setValueOperation); - FastGaussianBlurOperation *blurOperation = new FastGaussianBlurOperation(); + GaussianBokehBlurOperation *blurOperation = new GaussianBokehBlurOperation(); blurOperation->setData(&preBlurData); + blurOperation->setQuality(COM_QUALITY_HIGH); addLink(graph, separateOperation->getOutputSocket(0), blurOperation->getInputSocket(0)); addLink(graph, setValueOperation->getOutputSocket(0), blurOperation->getInputSocket(1)); @@ -104,8 +106,9 @@ OutputSocket *KeyingNode::setupPostBlur(ExecutionSystem *graph, OutputSocket *po setValueOperation->setValue(1.0f); graph->addOperation(setValueOperation); - FastGaussianBlurOperation *blurOperation = new FastGaussianBlurOperation(); + GaussianBokehBlurOperation *blurOperation = new GaussianBokehBlurOperation(); blurOperation->setData(&postBlurData); + blurOperation->setQuality(COM_QUALITY_HIGH); addLink(graph, postBLurInput, blurOperation->getInputSocket(0)); addLink(graph, setValueOperation->getOutputSocket(0), blurOperation->getInputSocket(1)); @@ -149,6 +152,20 @@ OutputSocket *KeyingNode::setupDespill(ExecutionSystem *graph, OutputSocket *des return despillOperation->getOutputSocket(0); } +OutputSocket *KeyingNode::setupClip(ExecutionSystem *graph, OutputSocket *clipInput, float clipBlack, float clipWhite) +{ + KeyingClipOperation *clipOperation = new KeyingClipOperation(); + + clipOperation->setClipBlack(clipBlack); + clipOperation->setClipWhite(clipWhite); + + addLink(graph, clipInput, clipOperation->getInputSocket(0)); + + graph->addOperation(clipOperation); + + return clipOperation->getOutputSocket(0); +} + void KeyingNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { InputSocket *inputImage = this->getInputSocket(0); @@ -163,9 +180,6 @@ void KeyingNode::convertToOperations(ExecutionSystem *graph, CompositorContext * /* keying operation */ KeyingOperation *keyingOperation = new KeyingOperation(); - keyingOperation->setClipBlack(keying_data->clip_black); - keyingOperation->setClipWhite(keying_data->clip_white); - inputScreen->relinkConnections(keyingOperation->getInputSocket(1), 1, graph); if (keying_data->blur_pre) { @@ -180,11 +194,14 @@ void KeyingNode::convertToOperations(ExecutionSystem *graph, CompositorContext * graph->addOperation(keyingOperation); + postprocessedMatte = keyingOperation->getOutputSocket(); + + if (keying_data->clip_black > 0.0f || keying_data->clip_white< 1.0f) + postprocessedMatte = setupClip(graph, postprocessedMatte, keying_data->clip_black, keying_data->clip_white); + /* apply blur on matte if needed */ if (keying_data->blur_post) - postprocessedMatte = setupPostBlur(graph, keyingOperation->getOutputSocket(), keying_data->blur_post); - else - postprocessedMatte = keyingOperation->getOutputSocket(); + postprocessedMatte = setupPostBlur(graph, postprocessedMatte, keying_data->blur_post); /* matte dilate/erode */ if (keying_data->dilate_distance != 0) { diff --git a/source/blender/compositor/nodes/COM_KeyingNode.h b/source/blender/compositor/nodes/COM_KeyingNode.h index 894d0ddc095..9d4067ce599 100644 --- a/source/blender/compositor/nodes/COM_KeyingNode.h +++ b/source/blender/compositor/nodes/COM_KeyingNode.h @@ -37,6 +37,7 @@ protected: OutputSocket *setupPostBlur(ExecutionSystem *graph, OutputSocket *postBLurInput, int size); OutputSocket *setupDilateErode(ExecutionSystem *graph, OutputSocket *dilateErodeInput, int distance); OutputSocket *setupDespill(ExecutionSystem *graph, OutputSocket *despillInput, InputSocket *inputSrceen, float factor); + OutputSocket *setupClip(ExecutionSystem *graph, OutputSocket *clipInput, float clipBlack, float clipWhite); public: KeyingNode(bNode *editorNode); void convertToOperations(ExecutionSystem *graph, CompositorContext *context); diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp new file mode 100644 index 00000000000..559d282f613 --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp @@ -0,0 +1,95 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_KeyingClipOperation.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" + +KeyingClipOperation::KeyingClipOperation(): NodeOperation() +{ + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + + this->clipBlack = 0.0f; + this->clipWhite = 1.0f; + + this->pixelReader = NULL; +} + +void KeyingClipOperation::initExecution() +{ + this->pixelReader = this->getInputSocketReader(0); +} + +void KeyingClipOperation::deinitExecution() +{ + this->pixelReader = NULL; +} + +void KeyingClipOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) +{ + const int delta = 3; + + float pixelColor[4]; + int width = this->getWidth(), height = this->getHeight(); + int count_black = 0, count_white = 0; + int i, j; + + this->pixelReader->read(pixelColor, x, y, sampler, inputBuffers); + + for (i = -delta + 1; i < delta; i++) { + for (j = -delta + 1; j < delta; j++) { + int cx = x + j, cy = y + i; + + if (i == 0 && j == 0) + continue; + + if (cx >= 0 && cx < width && cy >= 0 && cy < height) { + float value[4]; + + this->pixelReader->read(value, cx, cy, sampler, inputBuffers); + + if (value[0] < 0.4f) + count_black++; + else if (value[0] > 0.6f) + count_white++; + } + } + } + + color[0] = pixelColor[0]; + + if (count_black >= 22 || count_white >= 22) { + if (count_black >= 4 || count_white >= 4) { + if (color[0] < this->clipBlack) + color[0] = 0.0f; + else if (color[0] >= this->clipWhite) + color[0] = 1.0f; + else + color[0] = (color[0] - this->clipBlack) / (this->clipWhite - this->clipBlack); + } + } +} diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.h b/source/blender/compositor/operations/COM_KeyingClipOperation.h new file mode 100644 index 00000000000..1141e0b47ab --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingClipOperation.h @@ -0,0 +1,50 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#ifndef _COM_KeyingClipOperation_h +#define _COM_KeyingClipOperation_h + +#include "COM_NodeOperation.h" + +/** + * Class with implementation of black/white clipping for keying node + */ +class KeyingClipOperation : public NodeOperation { +protected: + SocketReader *pixelReader; + float clipBlack; + float clipWhite; + +public: + KeyingClipOperation(); + + void initExecution(); + void deinitExecution(); + + void setClipBlack(float value) {this->clipBlack = value;} + void setClipWhite(float value) {this->clipWhite = value;} + + void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp index 5f1c9d0640d..7d7ac378bed 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp @@ -28,26 +28,33 @@ #include "BLI_listbase.h" #include "BLI_math.h" -static int get_pixel_primary_channel(float *pixel) +static int get_pixel_primary_channel(float pixelColor[4]) { - float max_value = MAX3(pixel[0], pixel[1], pixel[2]); + float max_value = MAX3(pixelColor[0], pixelColor[1], pixelColor[2]); - if (max_value == pixel[0]) + if (max_value == pixelColor[0]) return 0; - else if (max_value == pixel[1]) + else if (max_value == pixelColor[1]) return 1; return 2; } -static float get_pixel_saturation(float *pixel, float screen_balance) +static float get_pixel_saturation(float pixelColor[4], float screen_balance, int primary_channel) { - float min = MIN3(pixel[0], pixel[1], pixel[2]); - float max = MAX3(pixel[0], pixel[1], pixel[2]); - float mid = pixel[0] + pixel[1] + pixel[2] - min - max; - float val = (1.0f - screen_balance) * min + screen_balance * mid; + int other_1 = (primary_channel + 1) % 3; + int other_2 = (primary_channel + 2) % 3; - return (max - val) * (1.0f - val) * (1.0f - val); + float min = MIN2(pixelColor[other_1], pixelColor[other_2]); + float max = MAX2(pixelColor[other_1], pixelColor[other_2]); + float val = screen_balance * min + (1.0f - screen_balance) * max; + + // original formula, also used by brecht + // works a bit crappy in areas with values > 1.0 + // return (pixelColor[primary_channel] - val) * fabsf(1.0f - val); + + // sergey's test formula + return pixelColor[1] - (pixelColor[0] + pixelColor[1]) * 0.5f; } KeyingOperation::KeyingOperation(): NodeOperation() @@ -57,8 +64,6 @@ KeyingOperation::KeyingOperation(): NodeOperation() this->addOutputSocket(COM_DT_VALUE); this->screenBalance = 0.5f; - this->clipBlack = 0.0f; - this->clipWhite = 1.0f; this->pixelReader = NULL; this->screenReader = NULL; @@ -84,31 +89,20 @@ void KeyingOperation::executePixel(float *color, float x, float y, PixelSampler this->pixelReader->read(pixelColor, x, y, sampler, inputBuffers); this->screenReader->read(screenColor, x, y, sampler, inputBuffers); - float saturation = get_pixel_saturation(pixelColor, this->screenBalance); - float screen_saturation = get_pixel_saturation(screenColor, this->screenBalance); - int primary_channel = get_pixel_primary_channel(pixelColor); - int screen_primary_channel = get_pixel_primary_channel(screenColor); + int primary_channel = get_pixel_primary_channel(screenColor); - if (primary_channel != screen_primary_channel) { - /* different main channel means pixel is on foreground */ + float saturation = get_pixel_saturation(pixelColor, this->screenBalance, primary_channel); + float screen_saturation = get_pixel_saturation(screenColor, this->screenBalance, primary_channel); + + if (saturation < 0) { color[0] = 1.0f; } - else if (saturation >= screen_saturation) { - /* saturation of main channel is more than screen, definitely a background */ + else if (saturation >= screen_saturation) { color[0] = 0.0f; } else { - float distance; + float distance = 1.0f - saturation / screen_saturation; - distance = 1.0f - saturation / screen_saturation; - - color[0] = distance * distance; - - if (color[0] < this->clipBlack) - color[0] = 0.0f; - else if (color[0] >= this->clipWhite) - color[0] = 1.0f; - else - color[0] = (color[0] - this->clipBlack) / (this->clipWhite - this->clipBlack); + color[0] = distance; } } diff --git a/source/blender/compositor/operations/COM_KeyingOperation.h b/source/blender/compositor/operations/COM_KeyingOperation.h index 546ff355573..0ce6481b835 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.h +++ b/source/blender/compositor/operations/COM_KeyingOperation.h @@ -39,8 +39,6 @@ protected: SocketReader *pixelReader; SocketReader *screenReader; float screenBalance; - float clipBlack; - float clipWhite; public: KeyingOperation(); @@ -48,9 +46,6 @@ public: void initExecution(); void deinitExecution(); - void setClipBlack(float value) {this->clipBlack = value;} - void setClipWhite(float value) {this->clipWhite = value;} - void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]); }; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index e97f3195f47..7567d40d9a5 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3095,7 +3095,7 @@ static void def_cmp_keying(StructRNA *srna) RNA_def_struct_sdna_from(srna, "NodeKeyingData", "storage"); - prop = RNA_def_property(srna, "despill_factor", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "despill_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "despill_factor"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Despill", ""); From 1acd2c58b6ea1bdce3b50385d5955eb4b50b4a93 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 Jun 2012 18:19:41 +0000 Subject: [PATCH 173/183] Actually that was an error in on of test formulas. Stick back to original one. --- .../blender/compositor/operations/COM_KeyingOperation.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp index 7d7ac378bed..a31b49c4a5c 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp @@ -49,12 +49,7 @@ static float get_pixel_saturation(float pixelColor[4], float screen_balance, int float max = MAX2(pixelColor[other_1], pixelColor[other_2]); float val = screen_balance * min + (1.0f - screen_balance) * max; - // original formula, also used by brecht - // works a bit crappy in areas with values > 1.0 - // return (pixelColor[primary_channel] - val) * fabsf(1.0f - val); - - // sergey's test formula - return pixelColor[1] - (pixelColor[0] + pixelColor[1]) * 0.5f; + return (pixelColor[primary_channel] - val) * fabsf(1.0f - val); } KeyingOperation::KeyingOperation(): NodeOperation() From a8bae06dc4c7e4181d9ee16ee23866b8eeba56ff Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 Jun 2012 18:26:26 +0000 Subject: [PATCH 174/183] Looks like some kind of merge error happened here which i didn't notice. Corrected! --- .../operations/COM_KeyingClipOperation.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp index 559d282f613..1c92e76c51a 100644 --- a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp @@ -83,13 +83,11 @@ void KeyingClipOperation::executePixel(float *color, float x, float y, PixelSamp color[0] = pixelColor[0]; if (count_black >= 22 || count_white >= 22) { - if (count_black >= 4 || count_white >= 4) { - if (color[0] < this->clipBlack) - color[0] = 0.0f; - else if (color[0] >= this->clipWhite) - color[0] = 1.0f; - else - color[0] = (color[0] - this->clipBlack) / (this->clipWhite - this->clipBlack); - } + if (color[0] < this->clipBlack) + color[0] = 0.0f; + else if (color[0] >= this->clipWhite) + color[0] = 1.0f; + else + color[0] = (color[0] - this->clipBlack) / (this->clipWhite - this->clipBlack); } } From 1c42677e6c393ea650569b4da1bc0148805fbcd7 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Sat, 9 Jun 2012 18:45:54 +0000 Subject: [PATCH 175/183] Formatting fixes in Ceres. --- .../third_party/ceres/include/ceres/autodiff_cost_function.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h index da9ee2c7993..e86d6993864 100644 --- a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h @@ -163,7 +163,7 @@ class AutoDiffCostFunction : explicit AutoDiffCostFunction(CostFunctor* functor) : functor_(functor) { CHECK_NE(M, DYNAMIC) << "Can't run the fixed-size constructor if the " - << "number of residuals is set to ceres::DYNAMIC."; + << "number of residuals is set to ceres::DYNAMIC."; } // Takes ownership of functor. Ignores the template-provided number of @@ -174,7 +174,7 @@ class AutoDiffCostFunction : AutoDiffCostFunction(CostFunctor* functor, int num_residuals) : functor_(functor) { CHECK_EQ(M, DYNAMIC) << "Can't run the dynamic-size constructor if the " - << "number of residuals is not ceres::DYNAMIC."; + << "number of residuals is not ceres::DYNAMIC."; SizedCostFunction::set_num_residuals(num_residuals); } From a844adc9c2a5c513f3a8b8de5a029aaffdd96d34 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Sat, 9 Jun 2012 18:58:51 +0000 Subject: [PATCH 176/183] Add new warp regularization scheme for planar tracking. This adds a new term to the tracking cost function that restricts how much the optimizer can warp the patch (as opposed to merely adjusting the translation). This should reduce the "jumpiness" that is sometimes seen when doing non-"Loc" tracks. It is disabled in this commit; a subsequent commit will add controls to the tracking dialog for this. --- extern/libmv/libmv/tracking/track_region.cc | 145 ++++++++++++++++---- extern/libmv/libmv/tracking/track_region.h | 17 +++ 2 files changed, 139 insertions(+), 23 deletions(-) diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index 679646c4c37..e65ead50c80 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -56,6 +56,7 @@ TrackRegionOptions::TrackRegionOptions() use_normalized_intensities(false), sigma(0.9), num_extra_points(0), + regularization_coefficient(0.0), image1_mask(NULL) { } @@ -137,9 +138,9 @@ class BoundaryCheckingCallback : public ceres::IterationCallback { }; template -class WarpCostFunctor { +class PixelDifferenceCostFunctor { public: - WarpCostFunctor(const TrackRegionOptions &options, + PixelDifferenceCostFunctor(const TrackRegionOptions &options, const FloatImage &image_and_gradient1, const FloatImage &image_and_gradient2, const Mat3 &canonical_to_image1, @@ -450,6 +451,79 @@ class WarpCostFunctor { FloatImage pattern_mask_; }; +template +class WarpRegularizingCostFunctor { + public: + WarpRegularizingCostFunctor(const TrackRegionOptions &options, + const double *x1, + const double *y1, + const double *x2_original, + const double *y2_original, + const Warp &warp) + : options_(options), + x1_(x1), + y1_(y1), + x2_original_(x2_original), + y2_original_(y2_original), + warp_(warp) { + // Compute the centroid of the first guess quad. + // TODO(keir): Use Quad class here. + original_centroid_[0] = 0.0; + original_centroid_[1] = 0.0; + for (int i = 0; i < 4; ++i) { + original_centroid_[0] += x2_original[i]; + original_centroid_[1] += y2_original[i]; + } + original_centroid_[0] /= 4; + original_centroid_[1] /= 4; + } + + template + bool operator()(const T *warp_parameters, T *residuals) const { + T dst_centroid[2] = { T(0.0), T(0.0) }; + for (int i = 0; i < 4; ++i) { + T image1_position[2] = { T(x1_[i]), T(y1_[i]) }; + T image2_position[2]; + warp_.Forward(warp_parameters, + T(x1_[i]), + T(y1_[i]), + &image2_position[0], + &image2_position[1]); + + // Subtract the positions. Note that this ignores the centroids. + residuals[2 * i + 0] = image2_position[0] - image1_position[0]; + residuals[2 * i + 1] = image2_position[1] - image1_position[1]; + + // Accumulate the dst centroid. + dst_centroid[0] += image2_position[0]; + dst_centroid[1] += image2_position[1]; + } + dst_centroid[0] /= T(4.0); + dst_centroid[1] /= T(4.0); + + // Adjust for the centroids. + for (int i = 0; i < 4; ++i) { + residuals[2 * i + 0] += T(original_centroid_[0]) - dst_centroid[0]; + residuals[2 * i + 1] += T(original_centroid_[1]) - dst_centroid[1]; + } + + // Reweight the residuals. + for (int i = 0; i < 8; ++i) { + residuals[i] *= T(options_.regularization_coefficient); + } + + return true; + } + + const TrackRegionOptions &options_; + const double *x1_; + const double *y1_; + const double *x2_original_; + const double *y2_original_; + double original_centroid_[2]; + const Warp &warp_; +}; + // Compute the warp from rectangular coordinates, where one corner is the // origin, and the opposite corner is at (num_samples_x, num_samples_y). Mat3 ComputeCanonicalHomography(const double *x1, @@ -1097,6 +1171,14 @@ void TemplatedTrackRegion(const FloatImage &image1, } // TODO(keir): Check quads to ensure there is some area. + // Keep a copy of the "original" guess for regularization. + double x2_original[4]; + double y2_original[4]; + for (int i = 0; i < 4; ++i) { + x2_original[i] = x2[i]; + y2_original[i] = y2[i]; + } + // Prepare the image and gradient. Array3Df image_and_gradient1; Array3Df image_and_gradient2; @@ -1138,26 +1220,43 @@ void TemplatedTrackRegion(const FloatImage &image1, num_samples_x, num_samples_y); - // Construct the warp cost function. AutoDiffCostFunction takes ownership. - WarpCostFunctor *warp_cost_function = - new WarpCostFunctor(options, - image_and_gradient1, - image_and_gradient2, - canonical_homography, - num_samples_x, - num_samples_y, - warp); - - // Construct the problem with a single residual. ceres::Problem problem; - problem.AddResidualBlock( - new ceres::AutoDiffCostFunction< - WarpCostFunctor, - ceres::DYNAMIC, - Warp::NUM_PARAMETERS>(warp_cost_function, - num_samples_x * num_samples_y), - NULL, - warp.parameters); + + // Construct the warp cost function. AutoDiffCostFunction takes ownership. + PixelDifferenceCostFunctor *pixel_difference_cost_function = + new PixelDifferenceCostFunctor(options, + image_and_gradient1, + image_and_gradient2, + canonical_homography, + num_samples_x, + num_samples_y, + warp); + problem.AddResidualBlock( + new ceres::AutoDiffCostFunction< + PixelDifferenceCostFunctor, + ceres::DYNAMIC, + Warp::NUM_PARAMETERS>(pixel_difference_cost_function, + num_samples_x * num_samples_y), + NULL, + warp.parameters); + + // Construct the regularizing cost function + if (options.regularization_coefficient != 0.0) { + WarpRegularizingCostFunctor *regularizing_warp_cost_function = + new WarpRegularizingCostFunctor(options, + x1, y2, + x2_original, + y2_original, + warp); + + problem.AddResidualBlock( + new ceres::AutoDiffCostFunction< + WarpRegularizingCostFunctor, + 8 /* num_residuals */, + Warp::NUM_PARAMETERS>(regularizing_warp_cost_function), + NULL, + warp.parameters); + } // Configure the solve. ceres::Solver::Options solver_options; @@ -1208,8 +1307,8 @@ void TemplatedTrackRegion(const FloatImage &image1, // Otherwise, run a final correlation check. if (options.minimum_correlation > 0.0) { - result->correlation = warp_cost_function-> - PearsonProductMomentCorrelationCoefficient(warp.parameters); + result->correlation = pixel_difference_cost_function-> + PearsonProductMomentCorrelationCoefficient(warp.parameters); if (result->correlation < options.minimum_correlation) { LG << "Failing with insufficient correlation."; result->termination = TrackRegionResult::INSUFFICIENT_CORRELATION; diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h index 04e7c7e1403..0de11239da6 100644 --- a/extern/libmv/libmv/tracking/track_region.h +++ b/extern/libmv/libmv/tracking/track_region.h @@ -73,6 +73,23 @@ struct TrackRegionOptions { // because the actual warp parameters are not exposed. int num_extra_points; + // For motion models other than translation, the optimizer sometimes has + // trouble deciding what to do around flat areas in the cost function. This + // leads to the optimizer picking poor solutions near the minimum. Visually, + // the effect is that the quad corners jiggle around, even though the center + // of the patch is well estimated. regularization_coefficient controls a term + // in the sum of squared error cost that makes it expensive for the optimizer + // to pick a warp that changes the shape of the patch dramatically (e.g. + // rotating, scaling, skewing, etc). + // + // In particular it adds an 8-residual cost function to the optimization, + // where each corner induces 2 residuals: the difference between the warped + // and the initial guess. However, the patch centroids are subtracted so that + // only patch distortions are penalized. + // + // If zero, no regularization is used. + double regularization_coefficient; + // If non-null, this is used as the pattern mask. It should match the size of // image1, even though only values inside the image1 quad are examined. The // values must be in the range 0.0 to 0.1. From 7bb79e777dd44d3d919a15b37d1bf4863c8d2856 Mon Sep 17 00:00:00 2001 From: Keir Mierle Date: Sat, 9 Jun 2012 19:22:39 +0000 Subject: [PATCH 177/183] Change libmv's bilinear sampling to assume the same pixel conventions as Blender. This fixes the preview widget, and should make tracking slightly more accurate. --- extern/libmv/libmv/image/sample.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/extern/libmv/libmv/image/sample.h b/extern/libmv/libmv/image/sample.h index 04a5748ea44..a8850effeab 100644 --- a/extern/libmv/libmv/image/sample.h +++ b/extern/libmv/libmv/image/sample.h @@ -59,6 +59,10 @@ inline T SampleLinear(const Array3D &image, float y, float x, int v = 0) { int x1, y1, x2, y2; float dx, dy; + // Take the upper left corner as integer pixel positions. + x -= 0.5; + y -= 0.5; + LinearInitAxis(y, image.Height(), &y1, &y2, &dy); LinearInitAxis(x, image.Width(), &x1, &x2, &dx); @@ -78,6 +82,10 @@ inline void SampleLinear(const Array3D &image, float y, float x, T *sample) { int x1, y1, x2, y2; float dx, dy; + // Take the upper left corner as integer pixel positions. + x -= 0.5; + y -= 0.5; + LinearInitAxis(y, image.Height(), &y1, &y2, &dy); LinearInitAxis(x, image.Width(), &x1, &x2, &dx); From fddeabeccf002d4e272fa5e5265f66a81a1ccbb7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 12:23:44 +0000 Subject: [PATCH 178/183] Somehow this files were missed in one of merges --- doc/python_api/examples/bpy.ops.2.py | 18 ++++++++++++++++++ doc/python_api/examples/bpy.ops.3.py | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 doc/python_api/examples/bpy.ops.2.py create mode 100644 doc/python_api/examples/bpy.ops.3.py diff --git a/doc/python_api/examples/bpy.ops.2.py b/doc/python_api/examples/bpy.ops.2.py new file mode 100644 index 00000000000..86b7438888c --- /dev/null +++ b/doc/python_api/examples/bpy.ops.2.py @@ -0,0 +1,18 @@ +""" +Overriding Context +++++++++++++++++++ + +It is possible to override context members that the operator sees, so that they +act on specified rather than the selected or active data, or to execute an +operator in the different part of the user interface. + +The context overrides are passed as a dictionary, with keys matching the context +member names in bpy.context. For example to override bpy.context.active_object, +you would pass {'active_object': object}. +""" + +# remove all objects in scene rather than the selected ones +import bpy +override = {'selected_bases': list(bpy.context.scene.object_bases)} +bpy.ops.object.delete(override) + diff --git a/doc/python_api/examples/bpy.ops.3.py b/doc/python_api/examples/bpy.ops.3.py new file mode 100644 index 00000000000..0b5bcafe5be --- /dev/null +++ b/doc/python_api/examples/bpy.ops.3.py @@ -0,0 +1,18 @@ +""" +It is also possible to run an operator in a particular part of the user +interface. For this we need to pass the window, screen, area and sometimes +a region. +""" + +# maximize 3d view in all windows +import bpy + +for window in bpy.context.window_manager.windows: + screen = window.screen + + for area in screen.areas: + if area.type == 'VIEW_3D': + override = {'window': window, 'screen': screen, 'area': area} + bpy.ops.screen.screen_full_area(override) + break + From e32fdad570e62910dd4d0e1e6b9b1ec5b53c4d4f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 12:31:07 +0000 Subject: [PATCH 179/183] Synchronize changes with trunk --- .../scripts/presets/operator/wm.collada_export/second_life.py | 1 + 1 file changed, 1 insertion(+) diff --git a/release/scripts/presets/operator/wm.collada_export/second_life.py b/release/scripts/presets/operator/wm.collada_export/second_life.py index 5e04903470b..151c4e55652 100644 --- a/release/scripts/presets/operator/wm.collada_export/second_life.py +++ b/release/scripts/presets/operator/wm.collada_export/second_life.py @@ -4,4 +4,5 @@ op = bpy.context.active_operator op.selected = True op.apply_modifiers = True op.include_bone_children = False +op.use_object_instantiation = False op.second_life = True From 39a97467d40ffb8c78a90c9c5f81e2e3068789d1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 13:25:04 +0000 Subject: [PATCH 180/183] Remove old preset which was corrected to Nicok D3S --- release/scripts/presets/camera/Nikon_D35.py | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 release/scripts/presets/camera/Nikon_D35.py diff --git a/release/scripts/presets/camera/Nikon_D35.py b/release/scripts/presets/camera/Nikon_D35.py deleted file mode 100644 index e6dc62dc100..00000000000 --- a/release/scripts/presets/camera/Nikon_D35.py +++ /dev/null @@ -1,4 +0,0 @@ -import bpy -bpy.context.object.data.sensor_width = 36.0 -bpy.context.object.data.sensor_height = 23.9 -bpy.context.object.data.sensor_fit = 'HORIZONTAL' From ecbd2842dce7e8cd058f9c7088de902cc791041d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 17:41:04 +0000 Subject: [PATCH 181/183] Add screen balance into interface Could be helpful to be played around. Default value is 0.5, Most probably this default value should be set manually for older files. --- source/blender/compositor/nodes/COM_KeyingNode.cpp | 2 ++ source/blender/compositor/operations/COM_KeyingOperation.h | 2 ++ source/blender/editors/space_node/drawnode.c | 1 + source/blender/makesdna/DNA_node_types.h | 1 + source/blender/makesrna/intern/rna_nodetree.c | 6 ++++++ .../blender/nodes/composite/nodes/node_composite_keying.c | 1 + 6 files changed, 13 insertions(+) diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp index 2bc502a5f86..05d4738de94 100644 --- a/source/blender/compositor/nodes/COM_KeyingNode.cpp +++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp @@ -180,6 +180,8 @@ void KeyingNode::convertToOperations(ExecutionSystem *graph, CompositorContext * /* keying operation */ KeyingOperation *keyingOperation = new KeyingOperation(); + keyingOperation->setScreenBalance(keying_data->screen_balance); + inputScreen->relinkConnections(keyingOperation->getInputSocket(1), 1, graph); if (keying_data->blur_pre) { diff --git a/source/blender/compositor/operations/COM_KeyingOperation.h b/source/blender/compositor/operations/COM_KeyingOperation.h index 0ce6481b835..1232d008ac8 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.h +++ b/source/blender/compositor/operations/COM_KeyingOperation.h @@ -46,6 +46,8 @@ public: void initExecution(); void deinitExecution(); + void setScreenBalance(float value) {this->screenBalance = value;} + void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]); }; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index aed282e4a4a..afaa7ac8a28 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2446,6 +2446,7 @@ static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), Poi /* bNode *node= ptr->data; */ /* UNUSED */ uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "screen_balance", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "despill_factor", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "clip_white", 0, NULL, ICON_NONE); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index a441936e054..cfc8ba526fa 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -633,6 +633,7 @@ typedef struct NodeKeyingScreenData { } NodeKeyingScreenData; typedef struct NodeKeyingData { + float screen_balance; float despill_factor; float clip_black, clip_white; int dilate_distance; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 7567d40d9a5..96258eff9c5 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3095,6 +3095,12 @@ static void def_cmp_keying(StructRNA *srna) RNA_def_struct_sdna_from(srna, "NodeKeyingData", "storage"); + prop = RNA_def_property(srna, "screen_balance", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "screen_balance"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Screen Balance", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); + prop = RNA_def_property(srna, "despill_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "despill_factor"); RNA_def_property_range(prop, 0.0f, 1.0f); diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c index b5f9b823ac2..16a9168e406 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keying.c +++ b/source/blender/nodes/composite/nodes/node_composite_keying.c @@ -196,6 +196,7 @@ static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode* node, bNo data = MEM_callocN(sizeof(NodeKeyingData), "node keying data"); + data->screen_balance = 0.5f; data->despill_factor = 1.0f; data->clip_black = 0.0f; data->clip_white = 1.0f; From b57403eebcf741fe72017ddebe268e1ed2e9d856 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 18:15:28 +0000 Subject: [PATCH 182/183] Make keying clamping operation complex so it might directly access input buffer Seems to give quite noticeable speedup, but there's sometimes strange artifacts showing as darker lines placed in along some kind of tiles. Not sure what causes them yet. --- .../operations/COM_KeyingClipOperation.cpp | 37 +++++++++---------- .../operations/COM_KeyingClipOperation.h | 8 ++-- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp index 1c92e76c51a..38d67a76c72 100644 --- a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp @@ -36,29 +36,30 @@ KeyingClipOperation::KeyingClipOperation(): NodeOperation() this->clipBlack = 0.0f; this->clipWhite = 1.0f; - this->pixelReader = NULL; + this->setComplex(true); } -void KeyingClipOperation::initExecution() +void *KeyingClipOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) { - this->pixelReader = this->getInputSocketReader(0); + void *buffer = getInputOperation(0)->initializeTileData(rect, memoryBuffers); + + return buffer; } -void KeyingClipOperation::deinitExecution() -{ - this->pixelReader = NULL; -} - -void KeyingClipOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) +void KeyingClipOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) { const int delta = 3; - float pixelColor[4]; - int width = this->getWidth(), height = this->getHeight(); + MemoryBuffer *inputBuffer = (MemoryBuffer*)data; + float *buffer = inputBuffer->getBuffer(); + + int bufferWidth = inputBuffer->getWidth(); + int bufferHeight = inputBuffer->getHeight(); + int count_black = 0, count_white = 0; int i, j; - this->pixelReader->read(pixelColor, x, y, sampler, inputBuffers); + int srcIndex = (y * bufferWidth + x) * 4; for (i = -delta + 1; i < delta; i++) { for (j = -delta + 1; j < delta; j++) { @@ -67,20 +68,18 @@ void KeyingClipOperation::executePixel(float *color, float x, float y, PixelSamp if (i == 0 && j == 0) continue; - if (cx >= 0 && cx < width && cy >= 0 && cy < height) { - float value[4]; + if (cx >= 0 && cx < bufferWidth && cy >= 0 && cy < bufferHeight) { + int bufferIndex = (cy * bufferWidth + cx) * 4; - this->pixelReader->read(value, cx, cy, sampler, inputBuffers); - - if (value[0] < 0.4f) + if (buffer[bufferIndex] < 0.4f) count_black++; - else if (value[0] > 0.6f) + else if (buffer[bufferIndex] > 0.6f) count_white++; } } } - color[0] = pixelColor[0]; + color[0] = buffer[srcIndex]; if (count_black >= 22 || count_white >= 22) { if (color[0] < this->clipBlack) diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.h b/source/blender/compositor/operations/COM_KeyingClipOperation.h index 1141e0b47ab..4eab7d6b0e3 100644 --- a/source/blender/compositor/operations/COM_KeyingClipOperation.h +++ b/source/blender/compositor/operations/COM_KeyingClipOperation.h @@ -31,20 +31,18 @@ */ class KeyingClipOperation : public NodeOperation { protected: - SocketReader *pixelReader; float clipBlack; float clipWhite; public: KeyingClipOperation(); - void initExecution(); - void deinitExecution(); - void setClipBlack(float value) {this->clipBlack = value;} void setClipWhite(float value) {this->clipWhite = value;} - void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]); + void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); + + void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data); }; #endif From 075b35572ecaa6e6e47e2e6e97c3711df74580ed Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 11 Jun 2012 09:18:55 +0000 Subject: [PATCH 183/183] This node was never actually commited to svn. --- source/blender/nodes/NOD_composite.h | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index efa107a2223..33d6327ece1 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -81,7 +81,6 @@ void register_node_type_cmp_bilateralblur(struct bNodeTreeType *ttype); void register_node_type_cmp_vecblur(struct bNodeTreeType *ttype); void register_node_type_cmp_dilateerode(struct bNodeTreeType *ttype); void register_node_type_cmp_defocus(struct bNodeTreeType *ttype); -void register_node_type_cmp_denoise(struct bNodeTreeType *ttype); void register_node_type_cmp_valtorgb(struct bNodeTreeType *ttype); void register_node_type_cmp_rgbtobw(struct bNodeTreeType *ttype);